
NAT를 사용할 때 libvirt/KVM을 실행하는 서버의 포트를 VM의 지정된 포트로 전달하려면 어떻게 해야 합니까?
예를 들어 호스트의 공용 IP는 1.2.3.4입니다. 포트 80을 10.0.0.1로, 포트 22를 10.0.0.2로 전달하고 싶습니다.
iptables 규칙을 추가해야 한다고 가정하지만 어디에 적절한지, 정확히 무엇을 지정해야 하는지 잘 모르겠습니다.
iptables -L의 출력
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT udp -- anywhere anywhere udp dpt:domain
ACCEPT tcp -- anywhere anywhere tcp dpt:domain
ACCEPT udp -- anywhere anywhere udp dpt:bootps
ACCEPT tcp -- anywhere anywhere tcp dpt:bootps
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere 10.0.0.0/24 state RELATED,ESTABLISHED
ACCEPT all -- 10.0.0.0/24 anywhere
ACCEPT all -- anywhere anywhere
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ifconfig의 출력
eth0 Link encap:Ethernet HWaddr 00:1b:fc:46:73:b9
inet addr:192.168.1.14 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::21b:fcff:fe46:73b9/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:201 errors:0 dropped:0 overruns:0 frame:0
TX packets:85 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:31161 (31.1 KB) TX bytes:12090 (12.0 KB)
Interrupt:17
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
virbr1 Link encap:Ethernet HWaddr ca:70:d1:77:b2:48
inet addr:10.0.0.1 Bcast:10.0.0.255 Mask:255.255.255.0
inet6 addr: fe80::c870:d1ff:fe77:b248/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:468 (468.0 B)
우분투 10.04를 사용하고 있습니다.
답변1
Ubuntu용 libvirt의 최신 안정 릴리스는 버전 0.7.5입니다. 이 버전에는 자동 네트워크 구성을 더 쉽게 해주는 몇 가지 새로운 기능(예: 스크립트 후크 및 네트워크 필터)이 없습니다. 즉, Ubuntu 10.04 Lucid Lynx에서 libvirt 0.7.5에 대한 포트 전달을 활성화하는 방법은 다음과 같습니다.
다음 iptables 규칙이 트릭을 수행해야 합니다.
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
기본 KVM NAT 구성은 위에서 제공한 세 번째 규칙과 유사한 규칙을 제공하지만 들어오는 연결을 수락하는 데 필수적인 NEW 상태를 생략합니다.
이러한 규칙을 추가하기 위해 시작 스크립트를 작성하고 주의하지 않은 경우 libvirt 0.7.5는 자체 규칙을 삽입하여 해당 규칙을 재정의합니다. 따라서 시작 시 이러한 규칙이 제대로 적용되도록 하려면 libvirt가 초기화되었는지 확인해야 합니다.~ 전에규칙을 삽입합니다.
/etc/rc.local의 줄 앞에 다음 줄을 추가합니다 exit 0
.
(
# Make sure the libvirt has started and has initialized its network.
while [ `ps -e | grep -c libvirtd` -lt 1 ]; do
sleep 1
done
sleep 10
# Set up custom iptables rules.
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
) &
위의 내용 sleep 10
은 우리가 자체 규칙을 추가하기 전에 libvirt 데몬이 iptables 규칙을 초기화할 기회를 가졌는지 확인하는 해킹입니다. Ubuntu용 libvirt 버전 0.8.3이 출시될 때까지 기다릴 수 없습니다.
답변2
즉석에서 포트 리디렉션을 설정하는 방법이 있습니다.게스트가 사용자 모드 네트워킹을 사용하는 경우, 여기에 대해 블로그에 올렸습니다.
http://blog.adamspiers.org/2012/01/23/port-redirection-from-kvm-host-to-guest/
거기에서 세부 사항을 볼 수 있지만 편의상 제가 알아낸 해결책은 다음과 같습니다.
virsh qemu-monitor-command --hmp sles11 'hostfwd_add ::2222-:22'
이 한 줄짜리 답변은 다른 답변보다 훨씬 쉽지만 일부 시나리오(사용자 모드 네트워크 스택)에서만 작동합니다.
답변3
이를 수행하는 보다 "공식적인"[1] 방법은 libvirt 웹 사이트에 설명된 대로 후크 스크립트를 만드는 것입니다.
http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections
... 기본적으로 이 스크립트는 KVM 게스트가 부팅될 때 호출됩니다. 스크립트 자체는 'NEW' 연결 상태가 올바르게 추가된 적절한 iptable 규칙(위의 Isaac Sutherland의 답변과 유사)을 추가합니다. 호스트 및 포트에 대한 올바른 값으로 스크립트를 수정해야 합니다.
[1] libvirt 문서 자체에는 이것이 일종의 해킹이라고 나와 있지만, 알아보세요.
답변4
/etc/libvirt/hooks/allow-portfw
Ubuntu 20.04에서는 (chmod +x) 로 저장되는 다음 스크립트를 만들었습니다 .
#!/bin/bash
CHAIN=LIBVIRT_FWI
IPTCMD="iptables -L $CHAIN -vn"
FILTERCMD="grep -v -e Chain -e pkts -e reject-with -e DNAT"
while $IPTCMD | grep ESTABLISHED | grep -v DNAT >/dev/null
do
IF=$($IPTCMD | $FILTERCMD | awk '{print $7}' | head -n1)
NET=$($IPTCMD | $FILTERCMD | awk '{print $9}' | head -n1)
iptables -D $CHAIN -o $IF -d $NET -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I $CHAIN 1 -o $IF -d $NET -m conntrack --ctstate DNAT,RELATED,ESTABLISHED -j ACCEPT
done
진입 상황은 NEW btw가 누락되었다는 것입니다. 자동으로 생성되는 FORWARDING 체인의 DNAT 플래그입니다.
sudo iptables -L LIBVIRT_FWI -vn
Chain LIBVIRT_FWI (1 references)
pkts bytes target prot opt in out source destination
1741K 2661M ACCEPT all -- * virbr0 0.0.0.0/0 192.168.122.0/24 ctstate RELATED,ESTABLISHED
38 1972 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
내 스크립트는 모든 정의에 DNAT 플래그를 추가합니다.
그런 식으로 방금 iptables에 포트 전달을 추가했습니다.
iptables -A PREROUTING -i mylanIF -p tcp --dport 3389 -j DNAT --to-destination 192.168.122.110:3389
패키지를 사용하여 iptables-persistent
이 상태를 저장할 수 있습니다(단, 덤프에서 libvirt 체인을 삭제해야 함).
ufw
아니면 다른 방화벽 스크립트를 사용하세요 .
내 스크립트는 이 주소에서 찾은 결과를 기반으로 합니다.https://www.cyberciti.biz/faq/kvm-forward-ports-to-guests-vm-with-ufw-on-linux/