%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%9C%20Linux%20%EB%9D%BC%EC%9A%B0%ED%8C%85.png)
내 설정:
이 설정에는 두 개의 네트워크 어댑터가 있는 가상 머신(VM)용 호스트 시스템인 물리적 머신이 하나만 있습니다.
하나의 NIC(eth0)는 내부 네트워크(LAN 서브넷, 예: 10.xxx/24)에 연결되며 내부 트래픽에 사용됩니다.
다른 NIC(eth1)는 공용 인터넷에 연결되어 있습니다(공용 라우팅 가능 IP가 구성되어 있음). 이 연결은 공용 인터넷 트래픽을 VM의 내부 IP(수신 트래픽)로 포트 전달하고 VM이 NAT를 통해 공용 인터넷(발신 트래픽)에 액세스할 수 있도록 하는 데 사용됩니다.
가상 머신은 LAN-Subnet(10.xxx/24, eth0과 동일)의 IP 주소를 사용합니다.
VM(vnet0, vnet1, ...) 및 LAN-NIC(eth0)의 가상 네트워크 인터페이스에 대해 구성된 브리지 장치(br0)가 있습니다. 그 의미는:
- br0에는 LAN 서브넷(10.xxx/24)의 IP 주소가 있습니다.
- eth0이 브릿지에 추가됩니다.
- vnet0, vnet1, ...(VM에서 사용)은 브리지에 동적으로 추가됩니다.
문제
LAN 내 통신이 제대로 작동합니다. 또한 VM-Host는 공용 IP를 통해 액세스할 수 있으며 인터넷에 액세스할 수 있습니다.
내 문제는 VM이 공용 인터넷에도 액세스할 수 있도록 허용하는 NAT 구성입니다.
간단한 (S)NAT 규칙을 사용해 보았습니다.
iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102
반면 yyy102는 두 번째 NIC(eth1)의 공개 라우팅 가능한 IP입니다.
"ip_forward" 및 "bridge-nf-call-iptables"를 활성화해야 한다는 것을 알았습니다.
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
그렇지 않으면 브리지된 패키지가 iptables에 의해 처리되지 않습니다.
이제 VM의 패킷은 다음과 같은 iptables 체인을 통과하는 것으로 보입니다.
- "FORWARD"(일반) - 거기에서 수락합니다(-j ACCEPT, 카운터가 올라갑니다).
- "PREROUTING"(nat) - 거기에서 수락합니다(정책 ACCEPT, 카운터가 올라갑니다).
- "POSTROUTING"(nat) - SNAT 규칙과 일치합니다.
그러나 지금까지 알 수 없었던 어떤 이유로든 모든 패킷이 PRE/POSTROUTING에 도착하지 않는 것 같습니다.
그러나 더 흥미롭게 tcpdump -i eth0
도 tcpdump -i eth1
패킷(VM 내에서 외부 IP를 ping하려고 시도함)이 잘못된 인터페이스 eth0(=LAN-NIC)을 통해 전송되는 것 같습니다. NAT 규칙도 적용되어 원본 주소가 다른 NIC(eth1)의 IP로 변경되었습니다.
질문:
올바른 NIC(eth1)를 통해 전송될 소스 주소로 공용 IP를 사용하여 NAT 패킷을 출력하도록 시스템을 구성하려면 어떻게 해야 합니까?
어떻게든 브리지(br0)에 eth1을 추가해야 합니까? 그렇다면 공인 IP 주소를 올바르게 할당하려면 어떻게 해야 합니까? 일반적으로 IP는 브리지 장치에 구성되어야 합니다. 브리지에 별칭 주소(br0:0의 공용 IP)를 할당해야 합니까?
구성 세부정보
호스트 시스템의 라우팅 구성:
# ip r
default via y.y.y.126 dev eth1
10.x.x.0/24 dev br0 proto kernel scope link src 10.x.x.11
y.y.y.96/27 dev eth1 proto kernel scope link src y.y.y.102
- IP: yyy126은 공용 인터넷용 라우터입니다.
- IP: yyy102는 호스트 시스템의 공용 IP입니다.
- IP: 10.xx11은 호스트 시스템의 LAN IP입니다.
- 서브넷: 10.xx0/24는 LAN입니다.
- 서브넷: yyy96/27은 공용 IP 서브넷입니다.
NIC 구성:
# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.x.x.11 netmask 255.255.255.0 broadcast 10.x.x.255
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 0 (Ethernet)
RX packets 2139490 bytes 243693436 (232.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29085 bytes 2398024 (2.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 1000 (Ethernet)
RX packets 2521995 bytes 290600491 (277.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 383089 bytes 48876399 (46.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xdfa60000-dfa7ffff
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet y.y.y.102 netmask 255.255.255.224 broadcast y.y.y.127
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 1000 (Ethernet)
RX packets 2681476 bytes 597532550 (569.8 MiB)
RX errors 0 dropped 130 overruns 0 frame 0
TX packets 187755 bytes 21894113 (20.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xdfa00000-dfa1ffff
브리지 구성:
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.002590eb1900 no eth0
vnet0
그리고 iptables 규칙은 다음과 같습니다.
# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
723 106K DROP udp -- * * y.y.y.0/24 0.0.0.0/0 udp spt:5404
586 40052 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
5 420 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
2 458 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 458 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1343 173K ACCEPT tcp -- * * 10.x.x.2 0.0.0.0/0 tcp spt:3389
1648 127K ACCEPT tcp -- * * 0.0.0.0/0 10.x.x.2 tcp dpt:3389
18 1040 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
18 1040 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 525 packets, 84016 bytes)
pkts bytes target prot opt in out source destination
# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 13 packets, 1218 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 5 packets, 420 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 13 packets, 880 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 14 packets, 920 bytes)
pkts bytes target prot opt in out source destination
5 300 SNAT all -- * * 10.x.x.0/24 !10.x.x.0/24 to:y.y.y.102
LAN 인터페이스 카드에서 캡처된 NAT 패킷(VM의 ping)은 다음과 같습니다.
# tcpdump -i eth0
12:53:55.243350 IP y.y.y.102 > y.y.y.110: ICMP echo request, id 2, seq 5, length 40
"ip 규칙"의 출력:
# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
답변1
VM에 10.xxx/24(넷마스크 255.255.255.0)의 IP 주소가 있는지 확인하세요.
10.xx11(br0 IP 주소)을 VM의 기본 게이트웨이로 설정합니다.
물리적 호스트에서 IP 전달 활성화
다음을 사용하여 SNAT를 활성화합니다.
iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102
답변2
iptables -t nat -I POSTROUTING -s 10.xxx/24 ! -d 10.xxx/24 -j SNAT --소스로 yyy102
이는 다음으로 변경되어야 합니다.
iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102
첫 번째 규칙에 따르면 대상이 10.xxx인 패키지만 처리해야 합니다. 그렇다면 외부에서 네트워크로 유입되는 트래픽은 어떻습니까? (출처 - 전 세계에서 대상은 공개 IP입니다 :)
올바른 NIC(eth1)를 통해 전송될 소스 주소로 공용 IP를 사용하여 NAT 패킷을 출력하도록 시스템을 구성하려면 어떻게 해야 합니까?
위에서 읽어보세요. NAT 규칙을 변경하면 됩니다.
어떻게든 브리지(br0)에 eth1을 추가해야 합니까? 그렇다면 공인 IP 주소를 올바르게 할당하려면 어떻게 해야 합니까? 일반적으로 IP는 브리지 장치에 구성되어야 합니다. 브리지에 별칭 주소(br0:0의 공용 IP)를 할당해야 합니까?
당신이 무엇을, 왜 이 일을 하고 있는지 알지 못한다면 결코 그렇지 않습니다. 내부 인터페이스와 외부 인터페이스를 별도로 유지하십시오. 라우팅만 허용합니다.
나는 5년 넘게 귀하의 구성 라이브(프로덕션)에 대해 설명했습니다. openvpn 터널을 통한 브리지 링크를 포함하여 3개의 호스트 서버와 25개의 VM에 대해 원활하게 작동합니다.
답변3
Silvio의 게시물은 비슷한 구성이 작동하는 데 도움이 되었습니다. 그의 게시물 외에도 제가 해야 할 일이 몇 가지 있습니다.
최신 버전의 Linux 커널(예: Redhat 7)에서는 브리지 커널 모듈을 활성화해야 합니다.
modprobe br_netfilter
그런 다음 서버를 다시 시작해도 해당 변경 사항이 지속되도록 하려면 /etc/modules-load.d/.conf라는 파일에 동일한 줄을 추가하세요.
br_netfilter를 활성화한 후에는 VM에 대한 iptable 전달 규칙도 활성화해야 했습니다. 예:
iptables -I FORWARD -d 10.x.x.x/24 -j ACCEPT iptables -I FORWARD -s 10.x.x.x/24 -j ACCEPT
SNAT 대신 서버 호스팅 시설 내에서 단일 경로만 필요했기 때문에 가장 무도회 규칙을 사용했습니다.
iptables -t nat -A POSTROUTING -s <single-local-vm-ip>/32 -d <my-destination-subnet>/24 -p tcp -j MASQUERADE --to-ports 1024-65535