OUTPUT 체인에서 DNAT를 사용하여 로컬에서 시작된 트래픽을 리디렉션하면 예상대로 작동하지 않습니다.

OUTPUT 체인에서 DNAT를 사용하여 로컬에서 시작된 트래픽을 리디렉션하면 예상대로 작동하지 않습니다.

나는 좀 바보같지만 여러분의 사랑스러운 사람들이 내 두뇌에 활기를 불어넣어 줄 수 있기를 바랍니다.

로컬 네트워크 네임스페이스에서 서비스를 실행하고 있습니다. 네임스페이스는 다음과 같습니다.

# ip -n ns1 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ns1-int@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 6e:35:ab:46:78:71 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.255.11/24 scope global ns1-int
       valid_lft forever preferred_lft forever
    inet6 fe80::6c35:abff:fe46:7871/64 scope link
       valid_lft forever preferred_lft forever

네임스페이스 라우팅 테이블은 다음과 같습니다.

$ ip -n ns1 route
default via 192.168.255.1 dev ns1-int
192.168.255.0/24 dev ns1-int proto kernel scope link src 192.168.255.11

인터페이스는 호스트에 연결된 ns1-int쌍의 한쪽 끝 입니다. 192.168.255.1은 다음 주소입니다:vethbr0br0

# ip addr show br0
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ce:10:da:46:71:fb brd ff:ff:ff:ff:ff:ff
    inet 192.168.255.1/24 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::cc10:daff:fe46:71fb/64 scope link
       valid_lft forever preferred_lft forever
# ip addr show master br0
5: ns1-ext@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP group default qlen 1000
    link/ether d6:69:bd:06:9c:fa brd ff:ff:ff:ff:ff:ff link-netns ns1
    inet6 fe80::d469:bdff:fe06:9cfa/64 scope link
       valid_lft forever preferred_lft forever

나는간단한 웹 서비스포트 80에서는 네임스페이스 주소를 사용하여 호스트에서 액세스할 수 있습니다.

# curl 192.168.255.11
Hostname: node1
IP: 127.0.0.1
IP: ::1
IP: 192.168.255.11
IP: fe80::6c35:abff:fe46:7871
RemoteAddr: 192.168.255.1:58396
GET / HTTP/1.1
Host: 192.168.255.11
User-Agent: curl/8.0.1
Accept: */*

이 서비스를 호스트 포트 8080에 노출하고 싶습니다. 둘 다 원격으로 트래픽을 시작하는 데 사용됩니다.그리고로컬에서 시작된 트래픽의 경우.

원격 트래픽은 문제가 되지 않습니다.

iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.255.11:80

이는 훌륭하게 작동합니다. 이제 네트워크의 다른 호스트에서 포트 8080의 동일한 웹 엔드포인트에 액세스할 수 있습니다.

anotherhost$ curl 192.168.121.67:8080
Hostname: node1
IP: 127.0.0.1
IP: ::1
IP: 192.168.255.11
IP: fe80::6c35:abff:fe46:7871
RemoteAddr: 192.168.121.1:47888
GET / HTTP/1.1
Host: 192.168.121.67:8080
User-Agent: curl/8.0.1
Accept: */*

또한 예를 들어 포트 8080을 사용하여 로컬로 서비스에 액세스할 수 있기를 원합니다 curl localhost:8080. 이론적으로 로컬에서 생성된 트래픽을 리디렉션하려면 OUTPUT체인에 하나의 규칙만 필요합니다.

iptables -t nat -A OUTPUT -p tcp --dport 8080 -j DNAT --to-destination 192.168.255.11:80

이때 전체 네트워크 파일 구성은 다음과 같습니다.

# iptables-save
# Generated by iptables-save v1.8.9 on Sun Jun 11 00:47:49 2023
*filter
:INPUT ACCEPT [751:53502]
:FORWARD ACCEPT [10:937]
:OUTPUT ACCEPT [433:43385]
COMMIT
# Completed on Sun Jun 11 00:47:49 2023
# Generated by iptables-save v1.8.9 on Sun Jun 11 00:47:49 2023
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [21:1580]
:POSTROUTING ACCEPT [22:1640]
-A PREROUTING -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.255.11:80
-A OUTPUT -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.255.11:80
COMMIT
# Completed on Sun Jun 11 00:47:49 2023

다음 항목에 액세스하려고 하면 localhost:8080중단됩니다 .

$ curl --connect-timeout 60 localhost:8080
curl: (28) Failed to connect to localhost port 8080 after 60001 ms: Timeout was reached

규칙은 OUTPUT확실히 일치합니다. 명령을 실행하면 curl적중 횟수가 증가하는 것을 볼 수 있습니다. 뭔가 단순한 것이 빠진 것 같은 느낌이 듭니다. 뭐가 될수 있었는지?

답변1

DNAT체인 의 규칙이 OUTPUT제대로 작동 하려면 두 가지 작업을 수행해야 합니다.

  1. 적절한 sysctl을 설정해야 합니다 route_localnet.

    sysctl -w net.ipv4.conf.br0.route_localnet
    

    이 변경으로 인해 네임스페이스 내에 다음과 같은 트래픽이 표시됩니다.

    03:23:02.984603 ns1-int In  IP 127.0.0.1.39656 > 192.168.255.11.80: Flags [S], seq 409674911, win 65495, options [mss 65495,sackOK,TS val 2257175047 ecr 0,nop,wscale 7], length 0
    

    이는 소스 주소( 127.0.0.1)가 쓸모가 없기 때문에 문제가 되므로...

  2. MASQUERADE교통 규칙을 만들어야 해~에서 localhost 도착하다네임스페이스:

    iptables -t nat -A POSTROUTING -s 127.0.0.1/32 -d 192.168.255.0/24 -j MASQUERADE
    

이 두 가지 규칙을 사용하면 모든 것이 예상대로 작동합니다.

# curl localhost:8080
Hostname: node1
IP: 127.0.0.1
IP: ::1
IP: 192.168.255.11
IP: fe80::8054:55ff:fef7:3e76
RemoteAddr: 192.168.255.1:36676
GET / HTTP/1.1
Host: localhost:8080
User-Agent: curl/8.0.1
Accept: */*

네임스페이스 내에서 들어오는 패킷이 이제 다음과 같은 모습을 볼 수 있습니다.

03:26:38.660882 ns1-int In  IP 192.168.255.1.38500 > 192.168.255.11.80: Flags [S], seq 1141073629, win 65495, options [mss 65495,sackOK,TS val 2257390724 ecr 0,nop,wscale 7], length 0

관련 정보