다음 명령을 사용하여 QEMU VM을 실행합니다.
qemu-system-x86_64 -enable-kvm -m 1024 -smp 2 -hda disk.qcow2
기본적으로 게스트 운영 체제는 인터넷에 액세스할 수 있지만 호스트 운영 체제의 열려 있는 포트에도 액세스할 수 있습니다. 게스트 OS가 호스트의 포트에 액세스하는 것을 방지하려면 어떻게 해야 합니까(인터넷 액세스는 제한하지 않음)?
답변1
고급 iptables 작업에 대한 경험이 없고 Linux가 로컬 프로세스 트래픽을 필터링하는 방법에 대한 개요가 없다면 문제가 될 수 있습니다.
귀하의 모드에서 qemu는 시뮬레이션된 NAT를 실행합니다. 게스트에서 NIC에 대한 모든 호출은 qemu 프로세스 자체에 의해 소켓/연결/보내기/수신 호출로 변환됩니다. 이는 연결이 127.0.0.1에서 머신 자체에 의해 설정됨을 의미합니다. 이 시점에서 다른 사용자로 qemu를 실행하고 일치 항목을 추가하여 해당 사용자를 필터링할 수 있습니다 owner
.
iptables -I OUTPUT -o lo -m owner --uid-owner username -m multiport --dports ports -j DROP
username
필터링할 사용자 이름은 어디에 있고 ports
이 컴퓨터에 대해 비활성화할 포트의 쉼표로 구분된 목록은 어디에 있습니까? 다른 사용자로 qemu를 실행하려면 user 또는 이와 유사한 방법 으로 실행하거나 sudo
로그인 해야 합니다 .su
login
이것이 없으면 스스로 필터링하게 되므로 포트를 필터링하는 일반 규칙을 추가하면 해당 포트에 대한 액세스도 차단됩니다.
또 다른 방법은 qemu의 네트워크 모드를 변경하는 것입니다. 트래픽을 필터링하는 좋은 방법은 qemu를 가상 이더넷 장치에 바인딩하는 것입니다.
패킷 전달을 활성화합니다.
을(를 ) 설치하려면
tunctl
귀하가 소유한 가상 네트워크 인터페이스를 추가하세요.
tunctl -u yourname -t qemu
rc.local
( 영구적으로 만드는 것과 같은 명령 에 이 명령을 추가하는 것을 잊지 마십시오 )
- 무료 /24 서브넷을 할당하도록 qemu 인터페이스를 구성합니다(
ip
/ 또는 기타 운영 체제 제공 도구 사용).ifconfig
이 서브넷은 게스트 운영 체제에도 설정되어야 합니다. 그런 다음-net tap,ifname=qemu,script=off
. 게스트 운영 체제 네트워크를 다시 구성하십시오.
qemu
그런 다음 가상 인터페이스로 표시되는 게스트 OS 트래픽을 쉽게 필터링할 수 있습니다.
iptables -I FORWARD -i qemu -m multiport --dports ports -j DROP
작동해야합니다.
그러나 NAT가 작동을 멈췄습니다. NAT를 다시 작동시키려면 컴퓨터에서 보낸 IP 주소를 패치하는 규칙을 추가해야 합니다. eth0
모든 트래픽이 통과하는 인터페이스가 있는 경우 NAT를 활성화합니다.
iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
답변2
-netdev user
기본() 네트워크를 사용하는 경우 몇 가지 더 간단한 방화벽 규칙이 있다는 점을 추가하고 싶습니다.
iptables -I OUTPUT -o lo -m owner --uid-owner qemu-user -d 127.0.0.1 -j DROP
user 아래에서 qemu를 실행해야 한다는 점에 유의 qemu-user
하세요.sudo -u qemu-user qemu-system-x86_64 -enable-kvm ......
이렇게 하면 호스트의 모든 포트를 지정하지 않고(첫 번째 답변에서와 같이) 게스트에 표시되는 것을 방지할 수 있습니다. 대상 주소(게스트가 기본적으로 보는 호스트의 주소)가 127.0.0.1
아닌 이유는 10.0.2.2
qemu가 NAT를 수행하는 방식 때문입니다.
관심이 있으신 경우 qemu가 기본 네트워킹을 처리하는 방법에 대한 자세한 내용은 다음과 같습니다.
Qemu는 가상화된 네트워크 카드에서 날아오는 원시 링크 계층 패킷으로 완료된 TCP 및 UDP 연결을 가로채서 , , , ...를 호출하여 qemu 프로세스 자체에서 실행되는 해당 연결로 변환합니다. socket()
그렇게 connect()
하는 sendto()
동안 recvfrom()
일부 주소 변환도 수행됩니다. 수행되므로 10.0.2.2
및 에 대한 연결은 각각 및 에 대한 연결 10.0.2.3
로 변환됩니다 . 그렇기 때문에 체인 규칙은 qemu의 연결을 끊고 호스트의 DNS 서버를 제외하고 게스트에게 호스트를 보이지 않게 만듭니다(그리고 qemu 내부에서 에뮬레이트된 DHCP 서버이지만 이 모든 작업은 qemu 내부에서 수행됩니다).127.0.0.1
127.0.0.53
OUTPUT
127.0.0.1
10.0.2.3
여기에서는 게스트가 다음을 사용하여 nslookup google.com 10.0.2.3
DNS 도메인을 확인할 때 qemu가 수행하는 네트워크 관련 시스템 호출을 볼 수 있습니다 .
$ sudo strace -f -e trace=network -p <qemu_pid>
strace: Process 14529 attached with 10 threads
[pid 14529] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 99
[pid 14529] sendto(99, "\236\353\1\0\0\1\0\0\0\0\0\0\6google\3com\0\0\1\0\1", 28, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 28
[pid 14529] recvfrom(99, "\236\353\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\1\0\1\300\f\0\1"..., 1500, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [128->16]) = 44
[pid 14529] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 100
[pid 14529] sendto(100, "@R\1\0\0\1\0\0\0\0\0\0\6google\3com\0\0\34\0\1", 28, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 28
[pid 14529] recvfrom(100, "@R\201\200\0\1\0\1\0\0\0\0\6google\3com\0\0\34\0\1\300\f\0\34"..., 1500, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [128->16]) = 56
보시 10.0.2.3
다시피 는 로 변환됩니다 127.0.0.53
. 게스트가 이 주소와 통신할 때 Qemu는 포트 53에 대한 UDP 트래픽만 허용하므로 호스트는 DNS 서버 데몬을 제외하고는 더 이상 노출되지 않습니다.