<scshin />

KVM·libvirt 가상 머신에 Oracle 19c 설치하고 포트 포워딩 설정하기

1.00

KVM·libvirt 가상 머신에 Oracle 19c 설치하고 포트 포워딩 설정하기


리눅스 서버에서 KVM과 libvirt를 이용하면 별도의 물리 서버 없이 가상 머신을 생성하고 운영할 수 있습니다.


1. 구성 환경

예제에서는 다음과 같은 환경을 사용합니다.

구분 설정값
호스트 운영체제 Ubuntu Linux
가상화 방식 KVM + libvirt
가상 머신 네트워크 libvirt NAT
가상 머신 IP 192.168.122.2
호스트 SSH 공개 포트 22222
가상 머신 SSH 포트 22
호스트 Oracle 공개 포트 11521
가상 머신 Oracle 포트 1521
Oracle SID ORCL
Oracle PDB ORCLPDB
Oracle 버전 Oracle Database 19c

전체 통신 구조는 다음과 같습니다.

외부 사용자
    │
    ├── HOST_IP:22222
    │         └── 192.168.122.2:22
    │
    └── HOST_IP:11521
              └── 192.168.122.2:1521

Oracle Database 19c 운영 환경은 Oracle Linux 또는 인증된 RHEL 계열 운영체제를 사용하는 것이 안전합니다.
Ubuntu에 Oracle 19c를 설치할 경우 호환성 우회 설정과 추가 패키지가 필요할 수 있으므로 실습 환경에서 사용하는 것을 권장합니다.


2. KVM 및 libvirt 설치

2.1 CPU 가상화 지원 확인

먼저 서버 CPU가 하드웨어 가상화를 지원하는지 확인합니다.

egrep -c '(vmx|svm)' /proc/cpuinfo

출력값이 1 이상이면 CPU에서 가상화 기능을 지원하는 것입니다.

  • vmx: Intel VT-x
  • svm: AMD-V

BIOS 또는 UEFI에서 가상화 기능이 비활성화되어 있다면 다음 항목을 활성화해야 합니다.

Intel Virtualization Technology
Intel VT-x
AMD-V
SVM Mode


2.2 KVM 관련 패키지 설치

Ubuntu 호스트에서 다음 패키지를 설치합니다.

apt update

apt install -y \
  qemu-kvm \
  libvirt-daemon-system \
  libvirt-clients \
  bridge-utils \
  virtinst \
  cpu-checker

각 패키지의 역할은 다음과 같습니다.

패키지 설명
qemu-kvm KVM 기반 가상 머신 실행
libvirt-daemon-system libvirt 데몬 및 시스템 서비스
libvirt-clients virsh 명령어 제공
bridge-utils 브리지 네트워크 관리
virtinst virt-install 명령어 제공
cpu-checker KVM 사용 가능 여부 확인

2.3 KVM 동작 확인

kvm-ok

정상적으로 사용할 수 있다면 다음과 비슷한 메시지가 출력됩니다.

INFO: /dev/kvm exists
KVM acceleration can be used

KVM 디바이스도 확인합니다.

ls -l /dev/kvm


2.4 libvirt 서비스 시작

systemctl enable --now libvirtd

서비스 상태를 확인합니다.

systemctl status libvirtd

등록된 가상 머신 목록을 확인합니다.

virsh list --all

아직 가상 머신을 생성하지 않았다면 빈 목록이 출력되는 것이 정상입니다.


3. libvirt 기본 네트워크 확인

libvirt는 일반적으로 default라는 NAT 네트워크를 사용합니다.

virsh net-list --all

다음과 같이 default 네트워크가 표시되어야 합니다.

 Name      State      Autostart   Persistent
------------------------------------------------
 default   active     yes         yes

네트워크가 존재하지만 비활성화되어 있다면 시작합니다.

virsh net-start default
virsh net-autostart default


3.1 default 네트워크가 없는 경우

다음과 같은 오류가 발생할 수 있습니다.

error: Network not found: no network with matching name 'default'

이 경우 기본 NAT 네트워크 정의 파일을 생성합니다.

cat <<'EOF' > /tmp/default-network.xml
<network>
  <name>default</name>
  <forward mode='nat'/>
  <bridge name='virbr0' stp='on' delay='0'/>
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
    </dhcp>
  </ip>
</network>
EOF

네트워크를 정의하고 시작합니다.

virsh net-define /tmp/default-network.xml
virsh net-start default
virsh net-autostart default

확인합니다.

virsh net-list --all
ip addr show virbr0

정상적으로 생성되면 virbr0 인터페이스에 다음 주소가 설정됩니다.

192.168.122.1/24


4. libvirt Storage Pool 생성

스토리지 풀은 가상 머신 디스크 이미지를 저장하고 관리하는 공간입니다.

가상 머신 이미지 디렉터리를 생성합니다.

mkdir -p /var/lib/libvirt/images

default 스토리지 풀을 정의합니다.

virsh pool-define-as \
  default \
  dir \
  --target /var/lib/libvirt/images

스토리지 풀을 시작합니다.

virsh pool-start default

서버 재부팅 후에도 자동으로 시작되도록 설정합니다.

virsh pool-autostart default

스토리지 풀 상태를 확인합니다.

virsh pool-list --all

정상적인 출력 예시는 다음과 같습니다.

 Name      State    Autostart
--------------------------------
 default   active   yes

스토리지 풀 상세 정보도 확인할 수 있습니다.

virsh pool-info default


4.1 이미 default 풀이 존재하는 경우

다음 오류가 발생한다면 기존 스토리지 풀이 이미 존재하는 것입니다.

error: storage pool 'default' already exists

기존 설정을 확인합니다.

virsh pool-dumpxml default
virsh pool-info default

잘못된 풀이 등록되어 있다면 먼저 제거한 후 다시 생성할 수 있습니다.

virsh pool-destroy default
virsh pool-undefine default

스토리지 풀을 삭제하기 전에 기존 가상 머신 디스크가 사용 중인지 반드시 확인해야 합니다.


5. 가상 머신 생성

ISO 파일을 스토리지 경로에 복사합니다.

cp ubuntu-24.04.iso /var/lib/libvirt/images/

다음 명령으로 가상 머신을 생성합니다.

virt-install \
  --name ubuntu24 \
  --memory 4096 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/ubuntu24.qcow2,size=40,format=qcow2 \
  --cdrom /var/lib/libvirt/images/ubuntu-24.04.iso \
  --os-variant ubuntu24.04 \
  --network network=default,model=virtio \
  --graphics vnc

각 옵션의 의미는 다음과 같습니다.

옵션 설명
--name ubuntu24 가상 머신 이름
--memory 4096 메모리 4GB
--vcpus 2 가상 CPU 2개
--disk 40GB QCOW2 디스크 생성
--cdrom 운영체제 설치 ISO
--os-variant 운영체제 최적화 정보
--network network=default libvirt 기본 NAT 네트워크
--graphics vnc VNC 설치 화면 제공

5.1 가상 머신 상태 확인

virsh list --all

가상 머신을 시작합니다.

virsh start ubuntu24

가상 머신을 종료합니다.

virsh shutdown ubuntu24

강제로 종료하려면 다음 명령을 사용합니다.

virsh destroy ubuntu24

virsh destroy는 전원 버튼을 강제로 끄는 것과 같으므로 정상 종료가 되지 않을 때만 사용해야 합니다.

자동 시작을 설정합니다.

virsh autostart ubuntu24


5.2 VNC 접속 정보 확인

virsh vncdisplay ubuntu24

예를 들어 다음과 같이 출력될 수 있습니다.

:0

이 경우 기본 VNC 포트는 다음과 같습니다.

5900 + 화면 번호

따라서 :0은 5900, :1은 5901입니다.

보안을 위해 VNC 포트를 외부에 직접 공개하기보다는 SSH 터널을 사용하는 것이 좋습니다.

ssh -L 5900:127.0.0.1:5900 사용자명@호스트IP


6. 가상 머신 IP 확인 및 고정

가상 머신 IP를 확인합니다.

virsh domifaddr ubuntu24

또는 가상 머신 내부에서 확인합니다.

ip addr

예제에서는 가상 머신 IP를 다음과 같이 사용합니다.

192.168.122.2

포트 포워딩 규칙은 특정 IP를 기준으로 설정되므로 가상 머신 IP가 변경되지 않도록 고정해야 합니다.

가상 머신의 MAC 주소는 다음 명령으로 확인할 수 있습니다.

virsh domiflist ubuntu24

출력 예시는 다음과 같습니다.

 Interface   Type      Source    Model    MAC
------------------------------------------------------
 vnet0       network   default   virtio   52:54:00:12:34:56

DHCP 예약을 사용하려면 다음과 같이 설정합니다.

virsh net-update default add ip-dhcp-host \
  "<host mac='52:54:00:12:34:56' name='ubuntu24' ip='192.168.122.2'/>" \
  --live \
  --config

설정 내용을 확인합니다.

virsh net-dumpxml default

설정 후 가상 머신의 DHCP 주소를 갱신하거나 재부팅합니다.

virsh reboot ubuntu24


7. Oracle Database 19c 설치 준비

Oracle 설치 작업은 가상 머신 내부에서 진행합니다.

Oracle Linux를 사용한다면 사전 설정 패키지를 사용하는 것이 가장 간단합니다.

dnf install -y oracle-database-preinstall-19c

해당 패키지를 사용할 수 없는 RHEL 계열 운영체제에서는 Oracle 설치에 필요한 패키지와 커널 파라미터를 별도로 설정해야 합니다.

대표적인 필수 패키지는 다음과 같습니다.

dnf install -y \
  bc \
  binutils \
  elfutils-libelf \
  elfutils-libelf-devel \
  fontconfig-devel \
  glibc \
  glibc-devel \
  ksh \
  libaio \
  libaio-devel \
  libnsl \
  libX11 \
  libXau \
  libXi \
  libXtst \
  libXrender \
  libXrender-devel \
  libgcc \
  libstdc++ \
  libstdc++-devel \
  libxcb \
  make \
  smartmontools \
  sysstat \
  unzip

운영체제 버전에 따라 패키지 이름이 다르거나 추가 저장소가 필요할 수 있습니다.


7.1 Oracle 그룹 및 계정 생성

Oracle 설치에 사용할 그룹을 생성합니다.

groupadd oinstall
groupadd dba

Oracle 계정이 없다면 생성합니다.

useradd -m -g oinstall -G dba oracle
passwd oracle

이미 Oracle 계정이 존재한다면 기본 그룹과 보조 그룹을 변경합니다.

usermod -g oinstall -aG dba oracle

계정 정보를 확인합니다.

id oracle

정상적인 출력 예시는 다음과 같습니다.

uid=1001(oracle) gid=1001(oinstall) groups=1001(oinstall),1002(dba)


7.2 Oracle 설치 디렉터리 생성

mkdir -p /u01/app/oracle/product/19.0.0/dbhome_1
mkdir -p /u01/app/oraInventory
mkdir -p /u01/app/oracle/oradata
mkdir -p /u01/app/oracle/fast_recovery_area

소유권과 권한을 변경합니다.

chown -R oracle:oinstall /u01/app
chmod -R 775 /u01/app

디렉터리 권한을 확인합니다.

ls -ld /u01/app
ls -ld /u01/app/oracle
ls -ld /u01/app/oraInventory


8. Oracle 환경 변수 설정

Oracle 계정으로 전환합니다.

su - oracle

Oracle 계정의 .bash_profile을 수정합니다.

vi ~/.bash_profile

다음 내용을 추가합니다.

export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export ORACLE_SID=ORCL

export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib64:/usr/lib64

export NLS_LANG=KOREAN_KOREA.AL32UTF8

운영체제 호환성 검사 우회가 필요한 실습 환경에서는 다음 값을 추가할 수 있습니다.

export CV_ASSUME_DISTID=OEL8.4

CV_ASSUME_DISTID는 설치 프로그램의 운영체제 검사를 우회하는 설정일 뿐, 해당 운영체제를 Oracle이 공식적으로 지원한다는 의미는 아닙니다.

변경 내용을 적용합니다.

source ~/.bash_profile

환경 변수를 확인합니다.

echo $ORACLE_BASE
echo $ORACLE_HOME
echo $ORACLE_SID
echo $PATH


9. Oracle 19c 설치 파일 압축 해제

Oracle 설치 파일을 Oracle 계정의 홈 디렉터리에 업로드합니다.

/home/oracle/LINUX.X64_193000_db_home.zip

Oracle Home 디렉터리로 이동합니다.

cd /u01/app/oracle/product/19.0.0/dbhome_1

압축을 해제합니다.

unzip /home/oracle/LINUX.X64_193000_db_home.zip

압축 해제 후 설치 파일을 확인합니다.

ls -l

다음 파일이 존재해야 합니다.

runInstaller


10. Oracle Database 19c 소프트웨어 설치

Oracle 계정으로 다음 명령을 실행합니다.

cd "$ORACLE_HOME"

자동 설치를 실행합니다.

./runInstaller \
  -silent \
  -waitforcompletion \
  -responseFile "$ORACLE_HOME/install/response/db_install.rsp" \
  oracle.install.option=INSTALL_DB_SWONLY \
  UNIX_GROUP_NAME=oinstall \
  INVENTORY_LOCATION=/u01/app/oraInventory \
  ORACLE_HOME="$ORACLE_HOME" \
  ORACLE_BASE="$ORACLE_BASE" \
  oracle.install.db.InstallEdition=EE \
  oracle.install.db.OSDBA_GROUP=dba \
  oracle.install.db.OSOPER_GROUP=dba \
  oracle.install.db.OSBACKUPDBA_GROUP=dba \
  oracle.install.db.OSDGDBA_GROUP=dba \
  oracle.install.db.OSKMDBA_GROUP=dba \
  oracle.install.db.OSRACDBA_GROUP=dba \
  SECURITY_UPDATES_VIA_MYORACLESUPPORT=false \
  DECLINE_SECURITY_UPDATES=true

주요 설정은 다음과 같습니다.

설정 설명
INSTALL_DB_SWONLY 데이터베이스 소프트웨어만 설치
INVENTORY_LOCATION Oracle Inventory 경로
InstallEdition=EE Enterprise Edition 설치
OSDBA_GROUP=dba DBA 운영체제 그룹
DECLINE_SECURITY_UPDATES=true 보안 업데이트 등록 생략

설치 로그는 일반적으로 다음 경로에서 확인할 수 있습니다.

ls -ltr /u01/app/oraInventory/logs


10.1 루트 스크립트 실행

설치 완료 메시지에 표시되는 루트 스크립트를 실행해야 합니다.

Oracle 계정에서 빠져나옵니다.

exit

root 계정으로 다음 스크립트를 실행합니다.

/u01/app/oraInventory/orainstRoot.sh
/u01/app/oracle/product/19.0.0/dbhome_1/root.sh

두 스크립트가 모두 정상적으로 완료되어야 Oracle 소프트웨어 설치가 끝납니다.


11. Oracle Listener 생성

Oracle 계정으로 전환합니다.

su - oracle

NETCA를 이용해 Listener를 생성합니다.

netca -silent \
  -responseFile "$ORACLE_HOME/assistants/netca/netca.rsp"

Listener 상태를 확인합니다.

lsnrctl status

Listener가 실행 중이 아니라면 시작합니다.

lsnrctl start

Listener를 중지하려면 다음 명령을 사용합니다.

lsnrctl stop

Listener가 사용하는 포트를 확인합니다.

ss -lntp | grep 1521

일반적으로 다음 주소에서 수신합니다.

0.0.0.0:1521

또는 서버의 특정 호스트명과 IP에서 수신할 수 있습니다.


12. Oracle 데이터베이스 생성

DBCA를 이용해 컨테이너 데이터베이스와 PDB를 생성합니다.

dbca -silent -createDatabase \
  -templateName General_Purpose.dbc \
  -gdbname ORCL \
  -sid ORCL \
  -createAsContainerDatabase true \
  -numberOfPDBs 1 \
  -pdbName ORCLPDB \
  -sysPassword 'Oracle비밀번호변경1!' \
  -systemPassword 'Oracle비밀번호변경1!' \
  -pdbAdminPassword 'Oracle비밀번호변경1!' \
  -databaseType MULTIPURPOSE \
  -memoryMgmtType auto_sga \
  -totalMemory 2048 \
  -storageType FS \
  -datafileDestination /u01/app/oracle/oradata \
  -recoveryAreaDestination /u01/app/oracle/fast_recovery_area \
  -characterSet AL32UTF8 \
  -nationalCharacterSet AL16UTF16 \
  -emConfiguration NONE

예제의 비밀번호는 반드시 실제 운영 환경에서 다른 강력한 비밀번호로 변경해야 합니다.

주요 옵션은 다음과 같습니다.

옵션 설명
-gdbname ORCL 글로벌 데이터베이스 이름
-sid ORCL 인스턴스 SID
-createAsContainerDatabase true CDB 방식으로 생성
-pdbName ORCLPDB PDB 이름
-totalMemory 2048 Oracle 사용 메모리 2GB
-characterSet AL32UTF8 데이터베이스 문자 집합
-emConfiguration NONE Enterprise Manager 미설치

데이터베이스 생성은 서버 성능에 따라 시간이 걸릴 수 있습니다.


12.1 PDB 상태 확인

SYSDBA 권한으로 접속합니다.

sqlplus / as sysdba

PDB 상태를 확인합니다.

SHOW PDBS;

PDB가 닫혀 있다면 실행합니다.

ALTER PLUGGABLE DATABASE ORCLPDB OPEN;

데이터베이스 재시작 후에도 PDB가 자동으로 열리도록 상태를 저장합니다.

ALTER PLUGGABLE DATABASE ORCLPDB SAVE STATE;

PDB 상태를 조회합니다.

SELECT NAME, OPEN_MODE
FROM V$PDBS;

정상적인 상태는 다음과 같습니다.

ORCLPDB   READ WRITE

SQL*Plus를 종료합니다.

EXIT;


13. Oracle 서비스 자동 시작 설정

13.1 oratab 설정

root 계정으로 /etc/oratab 파일을 수정합니다.

vi /etc/oratab

다음과 같이 마지막 값을 Y로 변경합니다.

ORCL:/u01/app/oracle/product/19.0.0/dbhome_1:Y

마지막 값의 의미는 다음과 같습니다.

값 설명
Y dbstart, dbshut 명령의 자동 시작·종료 대상
N 자동 시작·종료 대상에서 제외

13.2 systemd 서비스 파일 생성

vi /etc/systemd/system/oracle-db.service

다음 내용을 입력합니다.

[Unit]
Description=Oracle Database 19c
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
User=oracle
Group=oinstall

Environment=ORACLE_BASE=/u01/app/oracle
Environment=ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
Environment=ORACLE_SID=ORCL
Environment=PATH=/u01/app/oracle/product/19.0.0/dbhome_1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

ExecStart=/bin/bash -lc '$ORACLE_HOME/bin/lsnrctl start || true; $ORACLE_HOME/bin/dbstart $ORACLE_HOME'
ExecStop=/bin/bash -lc '$ORACLE_HOME/bin/dbshut $ORACLE_HOME; $ORACLE_HOME/bin/lsnrctl stop || true'

RemainAfterExit=yes
TimeoutStartSec=600
TimeoutStopSec=600

[Install]
WantedBy=multi-user.target

systemd 설정을 다시 읽습니다.

systemctl daemon-reload

Oracle 서비스를 활성화합니다.

systemctl enable oracle-db

서비스를 시작합니다.

systemctl start oracle-db

상태를 확인합니다.

systemctl status oracle-db


14. Oracle 데이터베이스 실행 상태 확인

Oracle PMON 프로세스를 확인합니다.

ps -ef | grep pmon | grep -v grep

정상적인 출력 예시는 다음과 같습니다.

oracle   12345  1  0 10:00 ?  00:00:00 ora_pmon_ORCL

Listener 상태도 확인합니다.

su - oracle -c "lsnrctl status"

Oracle 포트가 열려 있는지 확인합니다.

ss -lntp | grep 1521

Oracle 인스턴스 상태를 확인합니다.

su - oracle
sqlplus / as sysdba

SELECT INSTANCE_NAME, STATUS
FROM V$INSTANCE;

정상적인 상태는 다음과 같습니다.

INSTANCE_NAME   STATUS
--------------- ------------
ORCL            OPEN


15. 가상 머신 내부 방화벽 설정

가상 머신이 RHEL 계열이고 firewalld를 사용한다면 SSH와 Oracle 포트를 허용합니다.

firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=1521/tcp
firewall-cmd --reload

설정을 확인합니다.

firewall-cmd --list-all

Ubuntu 가상 머신에서 UFW를 사용한다면 다음과 같이 설정합니다.

ufw allow 22/tcp
ufw allow 1521/tcp
ufw reload


16. 호스트의 IPv4 포워딩 활성화

호스트에서 가상 머신으로 패킷을 전달하려면 IPv4 포워딩이 활성화되어 있어야 합니다.

현재 설정을 확인합니다.

sysctl net.ipv4.ip_forward

다음과 같이 출력되어야 합니다.

net.ipv4.ip_forward = 1

값이 0이라면 즉시 활성화합니다.

sysctl -w net.ipv4.ip_forward=1

재부팅 후에도 유지되도록 설정 파일을 생성합니다.

cat <<'EOF' > /etc/sysctl.d/99-vm-forward.conf
net.ipv4.ip_forward = 1
EOF

설정을 적용합니다.

sysctl --system


17. iptables 포트 포워딩 설정

외부에서 호스트의 특정 포트로 접속했을 때 가상 머신으로 전달하도록 구성합니다.

포트 포워딩 구성은 다음과 같습니다.

호스트 포트 가상 머신 주소 용도
22222 192.168.122.2:22 SSH
11521 192.168.122.2:1521 Oracle Listener

iptables의 테이블 이름은 대소문자를 구분하므로 NAT가 아니라 반드시 nat로 작성해야 합니다.


17.1 사용자 정의 체인 생성

이미 체인이 존재해도 오류로 중단되지 않도록 다음과 같이 실행합니다.

iptables -t nat -N VM_PREROUTING 2>/dev/null || true
iptables -t nat -N VM_POSTROUTING 2>/dev/null || true
iptables -N VM_FORWARD 2>/dev/null || true

기존 체인 규칙을 초기화합니다.

iptables -t nat -F VM_PREROUTING
iptables -t nat -F VM_POSTROUTING
iptables -F VM_FORWARD


17.2 DNAT 규칙 추가

호스트의 22222 포트를 가상 머신의 SSH 포트로 전달합니다.

iptables -t nat -A VM_PREROUTING \
  -p tcp \
  --dport 22222 \
  -j DNAT \
  --to-destination 192.168.122.2:22

호스트의 11521 포트를 가상 머신의 Oracle 포트로 전달합니다.

iptables -t nat -A VM_PREROUTING \
  -p tcp \
  --dport 11521 \
  -j DNAT \
  --to-destination 192.168.122.2:1521

외부 인터페이스가 eno1로 확정되어 있다면 다음과 같이 인터페이스를 제한할 수도 있습니다.

iptables -t nat -A VM_PREROUTING \
  -i eno1 \
  -p tcp \
  --dport 22222 \
  -j DNAT \
  --to-destination 192.168.122.2:22

iptables -t nat -A VM_PREROUTING \
  -i eno1 \
  -p tcp \
  --dport 11521 \
  -j DNAT \
  --to-destination 192.168.122.2:1521

인터페이스를 지정한 규칙과 지정하지 않은 규칙을 동시에 등록하지 말고 환경에 맞는 한 가지 방식만 사용합니다.

외부 인터페이스 이름은 다음 명령으로 확인할 수 있습니다.

ip route | grep default


17.3 POSTROUTING 설정

가상 머신 네트워크에서 외부로 나가는 패킷에 NAT를 적용합니다.

iptables -t nat -A VM_POSTROUTING \
  -s 192.168.122.0/24 \
  -j MASQUERADE

libvirt 기본 NAT 네트워크가 이미 MASQUERADE 규칙을 생성한 경우 이 규칙은 중복될 수 있습니다.

기존 규칙을 먼저 확인합니다.

iptables -t nat -L POSTROUTING -n -v


17.4 FORWARD 허용 규칙 추가

이미 연결된 세션의 응답 패킷을 허용합니다.

iptables -A VM_FORWARD \
  -m conntrack \
  --ctstate ESTABLISHED,RELATED \
  -j ACCEPT

가상 머신 SSH 접속을 허용합니다.

iptables -A VM_FORWARD \
  -p tcp \
  -d 192.168.122.2 \
  --dport 22 \
  -m conntrack \
  --ctstate NEW \
  -j ACCEPT

Oracle Listener 접속을 허용합니다.

iptables -A VM_FORWARD \
  -p tcp \
  -d 192.168.122.2 \
  --dport 1521 \
  -m conntrack \
  --ctstate NEW \
  -j ACCEPT


17.5 사용자 정의 체인 연결

PREROUTING 체인에 사용자 정의 체인을 연결합니다.

iptables -t nat -C PREROUTING -j VM_PREROUTING 2>/dev/null || \
iptables -t nat -A PREROUTING -j VM_PREROUTING

POSTROUTING 체인에 사용자 정의 체인을 연결합니다.

iptables -t nat -C POSTROUTING -j VM_POSTROUTING 2>/dev/null || \
iptables -t nat -A POSTROUTING -j VM_POSTROUTING

FORWARD 체인의 첫 번째 위치에 사용자 정의 체인을 연결합니다.

iptables -C FORWARD -j VM_FORWARD 2>/dev/null || \
iptables -I FORWARD 1 -j VM_FORWARD


17.6 전체 설정 명령

전체 명령을 한 번에 정리하면 다음과 같습니다.

# IPv4 포워딩 활성화
sysctl -w net.ipv4.ip_forward=1

# 사용자 정의 체인 생성
iptables -t nat -N VM_PREROUTING 2>/dev/null || true
iptables -t nat -N VM_POSTROUTING 2>/dev/null || true
iptables -N VM_FORWARD 2>/dev/null || true

# 기존 사용자 정의 체인 초기화
iptables -t nat -F VM_PREROUTING
iptables -t nat -F VM_POSTROUTING
iptables -F VM_FORWARD

# 포트 포워딩
iptables -t nat -A VM_PREROUTING \
  -p tcp --dport 22222 \
  -j DNAT --to-destination 192.168.122.2:22

iptables -t nat -A VM_PREROUTING \
  -p tcp --dport 11521 \
  -j DNAT --to-destination 192.168.122.2:1521

# 가상 머신 외부 통신 NAT
iptables -t nat -A VM_POSTROUTING \
  -s 192.168.122.0/24 \
  -j MASQUERADE

# 응답 패킷 허용
iptables -A VM_FORWARD \
  -m conntrack \
  --ctstate ESTABLISHED,RELATED \
  -j ACCEPT

# SSH 허용
iptables -A VM_FORWARD \
  -p tcp \
  -d 192.168.122.2 \
  --dport 22 \
  -m conntrack \
  --ctstate NEW \
  -j ACCEPT

# Oracle 허용
iptables -A VM_FORWARD \
  -p tcp \
  -d 192.168.122.2 \
  --dport 1521 \
  -m conntrack \
  --ctstate NEW \
  -j ACCEPT

# 사용자 정의 체인 연결
iptables -t nat -C PREROUTING -j VM_PREROUTING 2>/dev/null || \
iptables -t nat -A PREROUTING -j VM_PREROUTING

iptables -t nat -C POSTROUTING -j VM_POSTROUTING 2>/dev/null || \
iptables -t nat -A POSTROUTING -j VM_POSTROUTING

iptables -C FORWARD -j VM_FORWARD 2>/dev/null || \
iptables -I FORWARD 1 -j VM_FORWARD


18. iptables 규칙 확인

NAT 규칙을 확인합니다.

iptables -t nat -L -n -v --line-numbers

PREROUTING 사용자 정의 체인을 확인합니다.

iptables -t nat -L VM_PREROUTING -n -v --line-numbers

POSTROUTING 사용자 정의 체인을 확인합니다.

iptables -t nat -L VM_POSTROUTING -n -v --line-numbers

FORWARD 규칙을 확인합니다.

iptables -L VM_FORWARD -n -v --line-numbers

포트에 접속하면 pkts, bytes 값이 증가해야 합니다.


19. iptables 설정 영구 저장

Ubuntu에서 iptables 규칙은 서버를 재부팅하면 초기화될 수 있습니다.

영구 저장 패키지를 설치합니다.

apt install -y iptables-persistent

현재 규칙을 저장합니다.

netfilter-persistent save

또는 직접 저장할 수 있습니다.

iptables-save > /etc/iptables/rules.v4

저장된 규칙을 다시 불러오려면 다음 명령을 사용합니다.

iptables-restore < /etc/iptables/rules.v4

서비스 상태를 확인합니다.

systemctl status netfilter-persistent


20. 접속 테스트

20.1 호스트에서 가상 머신 접속 확인

먼저 호스트에서 가상 머신으로 직접 접속되는지 확인합니다.

SSH 포트 확인:

nc -vz 192.168.122.2 22

Oracle 포트 확인:

nc -vz 192.168.122.2 1521

직접 접속이 되지 않는다면 포트 포워딩보다 먼저 가상 머신의 서비스와 방화벽을 확인해야 합니다.


20.2 외부에서 SSH 접속

외부 PC에서 다음과 같이 접속합니다.

ssh -p 22222 사용자명@호스트IP

예시는 다음과 같습니다.

ssh -p 22222 oracle@192.168.0.10


20.3 외부에서 Oracle 포트 확인

nc -vz 호스트IP 11521

Windows PowerShell에서는 다음 명령을 사용할 수 있습니다.

Test-NetConnection 호스트IP -Port 11521


20.4 SQL*Plus 접속

sqlplus system/'Oracle비밀번호변경1!'@//호스트IP:11521/ORCLPDB

SID가 아니라 PDB 서비스명인 ORCLPDB를 사용한다는 점에 주의합니다.


20.5 JDBC 접속 문자열

Spring Boot 또는 Java 애플리케이션에서는 다음 형식을 사용합니다.

spring.datasource.url=jdbc:oracle:thin:@//호스트IP:11521/ORCLPDB
spring.datasource.username=SYSTEM
spring.datasource.password=Oracle비밀번호변경1!
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver

JDBC URL 형식은 다음과 같습니다.

jdbc:oracle:thin:@//호스트IP:11521/ORCLPDB


21. 주요 문제 해결 방법

21.1 Storage Pool을 찾을 수 없는 경우

오류 메시지:

error: Storage pool not found:
no storage pool with matching name 'default'

스토리지 풀을 생성합니다.

mkdir -p /var/lib/libvirt/images

virsh pool-define-as \
  default \
  dir \
  --target /var/lib/libvirt/images

virsh pool-start default
virsh pool-autostart default


21.2 default 네트워크를 찾을 수 없는 경우

virsh net-list --all

네트워크가 존재하면 시작합니다.

virsh net-start default
virsh net-autostart default

네트워크 자체가 없다면 앞에서 설명한 XML 파일을 이용해 새로 정의합니다.


21.3 가상 머신 IP가 변경되는 경우

iptables는 192.168.122.2로 전달하도록 설정되어 있습니다.

VM IP가 변경되면 포트 포워딩이 동작하지 않습니다.

다음을 확인합니다.

virsh domifaddr ubuntu24
virsh net-dhcp-leases default

해결 방법은 다음 중 하나입니다.

  1. libvirt DHCP 예약 설정
  2. 가상 머신 내부에서 고정 IP 설정
  3. 변경된 IP에 맞게 iptables DNAT 규칙 수정

21.4 Oracle 1521 포트가 열리지 않는 경우

Listener 상태를 확인합니다.

su - oracle
lsnrctl status

Listener를 시작합니다.

lsnrctl start

포트를 확인합니다.

ss -lntp | grep 1521

가상 머신 방화벽도 확인합니다.

firewall-cmd --list-all


21.5 ORA-12514 오류가 발생하는 경우

대표적인 오류 메시지는 다음과 같습니다.

ORA-12514: TNS:listener does not currently know of service requested

Listener에 등록된 서비스명을 확인합니다.

lsnrctl services

PDB 상태를 확인합니다.

sqlplus / as sysdba

SHOW PDBS;

PDB를 실행하고 상태를 저장합니다.

ALTER PLUGGABLE DATABASE ORCLPDB OPEN;
ALTER PLUGGABLE DATABASE ORCLPDB SAVE STATE;

접속 주소에는 SID인 ORCL이 아니라 서비스명인 ORCLPDB를 사용합니다.

//호스트IP:11521/ORCLPDB


21.6 외부에서 포트 접속이 되지 않는 경우

IPv4 포워딩을 확인합니다.

sysctl net.ipv4.ip_forward

iptables 카운터를 확인합니다.

iptables -t nat -L VM_PREROUTING -n -v
iptables -L VM_FORWARD -n -v

패킷이 호스트까지 들어오는지 확인합니다.

tcpdump -ni any port 22222

Oracle 포트는 다음과 같이 확인합니다.

tcpdump -ni any port 11521

호스트 자체 방화벽도 확인해야 합니다.

ufw status

필요한 경우 호스트 공개 포트를 허용합니다.

ufw allow 22222/tcp
ufw allow 11521/tcp

공유기나 상위 방화벽이 존재한다면 해당 장비에서도 포트 허용 또는 포트 포워딩 설정이 필요합니다.


21.7 Oracle 서비스가 부팅 후 실행되지 않는 경우

서비스 상태를 확인합니다.

systemctl status oracle-db

로그를 확인합니다.

journalctl -u oracle-db -b

/etc/oratab 설정을 확인합니다.

cat /etc/oratab

다음과 같이 마지막 값이 Y여야 합니다.

ORCL:/u01/app/oracle/product/19.0.0/dbhome_1:Y

Oracle 계정으로 직접 실행해 오류를 확인할 수도 있습니다.

su - oracle
dbstart "$ORACLE_HOME"
lsnrctl start


22. 포트 포워딩 규칙 제거

사용자 정의 체인의 연결 규칙을 제거합니다.

iptables -t nat -D PREROUTING -j VM_PREROUTING
iptables -t nat -D POSTROUTING -j VM_POSTROUTING
iptables -D FORWARD -j VM_FORWARD

체인 내부 규칙을 초기화합니다.

iptables -t nat -F VM_PREROUTING
iptables -t nat -F VM_POSTROUTING
iptables -F VM_FORWARD

사용자 정의 체인을 삭제합니다.

iptables -t nat -X VM_PREROUTING
iptables -t nat -X VM_POSTROUTING
iptables -X VM_FORWARD

변경된 규칙을 영구 저장합니다.

netfilter-persistent save


23. 보안 설정 권장 사항

운영 환경에서는 모든 외부 IP에 Oracle 포트를 공개하지 않는 것이 좋습니다.

특정 관리 IP만 SSH에 접근하도록 제한할 수 있습니다.

iptables -t nat -A VM_PREROUTING \
  -p tcp \
  -s 203.0.113.10 \
  --dport 22222 \
  -j DNAT \
  --to-destination 192.168.122.2:22

Oracle 접속도 허용된 애플리케이션 서버 IP로 제한합니다.

iptables -t nat -A VM_PREROUTING \
  -p tcp \
  -s 203.0.113.20 \
  --dport 11521 \
  -j DNAT \
  --to-destination 192.168.122.2:1521

추가로 다음 보안 설정을 권장합니다.

  • SSH 비밀번호 인증 대신 공개 키 인증 사용
  • root 원격 로그인 비활성화
  • Oracle 기본 계정 비밀번호 변경
  • Oracle 1521 포트의 전체 인터넷 공개 금지
  • 허용할 외부 IP를 방화벽으로 제한
  • 불필요한 VNC 포트 외부 공개 금지
  • Oracle 데이터 및 설정 파일 정기 백업
  • iptables 규칙 변경 전 기존 설정 백업

iptables 규칙은 다음 명령으로 백업할 수 있습니다.

iptables-save > /root/iptables-backup-$(date +%Y%m%d).rules

복원 명령은 다음과 같습니다.

iptables-restore < /root/iptables-backup-20260806.rules


24. 최종 확인 명령어

호스트에서 확인

virsh list --all
virsh net-list --all
virsh pool-list --all
virsh domifaddr ubuntu24
sysctl net.ipv4.ip_forward
iptables -t nat -L VM_PREROUTING -n -v
iptables -L VM_FORWARD -n -v

가상 머신에서 확인

ps -ef | grep pmon | grep -v grep
ss -lntp | grep 1521
systemctl status oracle-db
su - oracle -c "lsnrctl status"

외부 PC에서 확인

ssh -p 22222 사용자명@호스트IP
nc -vz 호스트IP 11521

Oracle 접속 주소는 다음과 같습니다.

호스트: 호스트 서버 IP
포트: 11521
서비스명: ORCLPDB

JDBC URL은 다음과 같습니다.

jdbc:oracle:thin:@//호스트IP:11521/ORCLPDB