상태 비저장 NAT는 글로벌 네트워크 네임스페이스의 물리적 네트워크 어댑터(가상 네트워크 어댑터의 연결된 쌍을 통해)에서 특수 네트워크 네임스페이스에서 실행되는 서비스로의 두 개의 UDP 연결을 위해 설정되어야 합니다. 이 작업은 커널이 포함된 Linux(Debian)를 실행하는 산업용 장치의 CPU(Intel Atom)에서 수행되어야 합니다.5.9.7.
설정해야 하는 네트워크 구성 시나리오는 다음과 같습니다.
===================== =====================================================
|| application CPU || || communication CPU ||
|| || || ||
|| || || global namespace | nsprot1 namespace ||
|| || || | ||
|| enp4s0 || || enp1s0 | enp3s0 ||
|| 0.0.0.5/30 ========== 0.0.0.6/30 | 192.168.2.15/24 =======
|| || || | ||
|| UDP port 50001 || || UDP port 50001 for sv1 | TCP port 2404 for sv2 ||
|| UDP port 50002 || || UDP port 50002 for sv1 | ||
|| UDP port 53401 || || UDP port 50401 for sv1 | ||
|| UDP port 53402 || || UDP port 50402 for sv1 | ||
|| || || | ||
|| || || vprot0 | vprot1 ||
|| || || 0.0.0.16/31 --- 0.0.0.17/31 ||
|| || || | ||
|| UDP port 53404 || || UDP port 50404 for sv2 - UDP port 50404 for sv2 ||
|| UDP port 53441 || || UDP port 50441 for sv2 - UDP port 50441 for sv2 ||
===================== =====================================================
애플리케이션 CPU는 항상 먼저 시작되고 sv1
IP 주소가 있는 물리적 네트워크 어댑터를 통해 통신 CPU의 서비스 및 서비스와 통신하기 위해 여러 UDP 포트를 엽니다.sv2
enp4s0
0.0.0.5
애플리케이션 CPU에서 실행될 때의 출력은 다음 ss --ipv4 --all --numeric --processes --udp
과 같습니다.
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 0.0.0.0:50001 0.0.0.0:* users:(("sva",pid=471,fd=5))
udp UNCONN 0 0 0.0.0.0:50002 0.0.0.0:* users:(("sva",pid=471,fd=6))
udp ESTAB 0 0 0.0.0.5:53401 0.0.0.6:50401 users:(("sva",pid=471,fd=12))
udp ESTAB 0 0 0.0.0.5:53402 0.0.0.6:50402 users:(("sva",pid=471,fd=13))
udp ESTAB 0 0 0.0.0.5:53404 0.0.0.6:50404 users:(("sva",pid=471,fd=19))
udp ESTAB 0 0 0.0.0.5:53441 0.0.0.6:50441 users:(("sva",pid=471,fd=21))
통신 CPU가 두 번째로 시작되고 마지막으로 두 가지 서비스가 실행됩니다.
sv1
전역 네임스페이스에서그리고sv2
특별한 네트워크 네임스페이스에 있습니다nsprot1
.
ss --ipv4 --all --numeric --processes --udp
통신 CPU의 전역 네임스페이스에서 실행한 결과는 다음과 같습니다.
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 0.0.0.0:50001 0.0.0.0:* users:(("sv1",pid=812,fd=18))
udp UNCONN 0 0 0.0.0.6:50002 0.0.0.0:* users:(("sv1",pid=812,fd=17))
udp UNCONN 0 0 0.0.0.6:50401 0.0.0.0:* users:(("sv1",pid=812,fd=13))
udp UNCONN 0 0 0.0.0.6:50402 0.0.0.0:* users:(("sv1",pid=812,fd=15))
ip netns exec nsprot1 ss --ipv4 --all --numeric --processes --udp
(네임스페이스)의 출력은 다음 nsprot1
과 같습니다.
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp ESTAB 0 0 0.0.0.17:50404 0.0.0.5:53404 users:(("sv2",pid=2421,fd=11))
udp ESTAB 0 0 0.0.0.17:50441 0.0.0.5:53441 users:(("sv2",pid=2421,fd=12))
sysctl
일반적으로 모든 물리적 네트워크 어댑터에는 IPv4 전달이 활성화되어 있습니다.
브로드캐스트 및 멀티캐스트 전달만 필요하지도 않고 원하지도 않으므로 비활성화됩니다.
다음 명령을 사용하여 통신 CPU의 네트워크 구성을 설정합니다.
ip netns add nsprot1
ip link add vprot0 type veth peer name vprot1 netns nsprot1
ip link set dev enp3s0 netns nsprot1
ip address add 0.0.0.16/31 dev vprot0
ip netns exec nsprot1 ip address add 0.0.0.17/31 dev vprot1
ip netns exec nsprot1 ip address add 192.168.2.15/24 dev enp3s0
ip link set dev vprot0 up
ip netns exec nsprot1 ip link set vprot1 up
ip netns exec nsprot1 ip link set enp3s0 up
ip netns exec nsprot1 ip route add 0.0.0.4/30 via 0.0.0.16 dev vprot1
다음 명령을 사용하여 네트워크 주소 변환을 설정합니다.
nft add table ip prot1
nft add chain ip prot1 prerouting '{ type nat hook prerouting priority -100; policy accept; }'
nft add rule prot1 prerouting iif enp1s0 udp dport '{ 50404, 50441 }' dnat 0.0.0.17
nft add chain ip prot1 postrouting '{ type nat hook postrouting priority 100; policy accept; }'
nft add rule prot1 postrouting ip saddr 0.0.0.16/31 oif enp1s0 snat 0.0.0.6
출력은 nft list table ip prot1
다음과 같습니다
table ip prot1 {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
iif "enp1s0" udp dport { 50404, 50441 } dnat to 0.0.0.17
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 0.0.0.16/31 oif "enp1s0" snat to 0.0.0.6
}
}
전역 네임스페이스에 추가로 정의됩니다.오직테이블에는 다음 inet filter
이 포함됩니다.
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
이 NAT 구성은 상태 저장 NAT용입니다. 이는 포트 번호가 있는 UDP 채널에서 작동하며 50404
마지막 으로 시작된 53404
이후 UDP 패킷을 sv2
열어 전송합니다. 이 패킷에는 전역 네임스페이스의 후크에 소스 네트워크 주소 변환이 적용됩니다. 응용 프로그램 CPU 서비스는 UDP 패킷을 에서 로 다시 보냅니다. UDP 패킷이 에 대한 규칙을 전달하지 않았습니다. 나중에 발견한 대로 연결 추적을 통해 직접 전송되었습니다.0.0.0.17:50404
0.0.0.5:53404
postrouting
enp1s0
sva
0.0.0.5:53404
0.0.0.6:50404
0.0.0.17:50404
prerouting
dnat
0.0.0.17
0.0.0.17
그러나 이 상태 저장 NAT 구성은 포트 번호가 50441
및 인 UDP 채널에는 적용되지 않습니다 534441
. 원인은 sva
서비스가 시작되기 전에 애플리케이션 CPU가 여러 UDP 패킷을 보냈고 대상 포트가 0.0.0.5:53441
네트워크 네임스페이스에 열려 있기 때문인 것 같습니다. ICMP는 대상 포트에 연결할 수 없다고 반환합니다. 목적지 항구가 아직 열려 있지 않다는 점을 고려하면 이는 놀라운 일이 아닙니다. 불행하게도 서비스가 시작되고 두 UDP 포트가 모두 열릴 때까지 UDP 패킷이 서비스에서 전송되는 것을 방지할 수 있는 방법은 없습니다. 이 서비스는 연결 상태에 관계없이 주기적으로 전송하고 때로는 추가로 자발적인 UDP 패킷을 트리거합니다.0.0.0.6:50441
sv2
nsprot1
sva
sv2
sva
0.0.0.5:53441
0.0.0.6:50441
따라서 이 구성의 문제는 상태 저장 NAT인 것 같습니다. 후크 dnat
의 규칙 prerouting
이 네트워크 네임스페이스에서 열리게 되는 대상 포트에서 여전히 사용되지 않기 때문입니다 nsprot1
. UDP 패킷은 어쨌든 계속 라우팅되므로 0.0.0.6:50441
UDP 패킷이 삭제되고 대상 포트에 연결할 수 없음을 나타내는 ICMP가 반환됩니다.
따라서 해결책은 Stateless NAT를 사용하는 것일 수 있습니다. 따라서 다음 명령도 실행되었습니다.
nft add table ip raw
nft add chain ip raw prerouting '{ type filter hook prerouting priority -300; policy accept; }'
nft add rule ip raw prerouting udp dport '{ 50404, 50441, 53404, 53441 }' notrack
그러나 결과는 예상과 달랐다. 입력 인터페이스와 대상 포트에서 들어오는 UDP 패킷의 경우 prerouting
대상 주소를 에서 로 변경하는 규칙 0.0.0.6
은 아직 고려되지 않습니다.0.0.0.17
enp1s0
50404
50441
다음은 내가 실행한 것입니다.
nft add table ip filter
nft add chain filter trace_in '{ type filter hook prerouting priority -301; }'
nft add rule filter trace_in meta nftrace set 1
nft add chain filter trace_out '{ type filter hook postrouting priority 99; }'
nft add rule filter trace_out meta nftrace set 1
nft monitor trace
추적을 살펴보니 notrack
규칙이 고려되었지만 대상 포트가 있는 UDP 패킷이 후크 50441
로 직접 전달되는 것을 볼 수 있습니다. input
이유는 모르겠습니다.
나는 다음과 같은 내용을 아주 오랜 시간 동안 매우 주의 깊게 연구했습니다.
- NFT 핸드북(위에서 아래로 여러 번 완전히 읽으십시오)
- nftables 위키(대부분의 페이지가 완료됨)
- ArchWiki의 nftables
- 그리고 네트워크 네임스페이스 사용 및 네트워크 주소 변환에 관한 수많은 기타 웹 페이지가 있습니다.
Wireshark를 사용하여 다양한 구성을 시도했지만 포트가 있는 UDP 채널에 대해 작동 하고 대상 포트가 열리기 전에 UDP 패킷을 보내는 nft monitor trace
솔루션을 찾을 수 없습니다 .50441
53441
sva
0.0.0.17:50441
애플리케이션 CPU에서 서비스를 수동으로 종료하고 sva
, 통신 CPU에서 네트워크 구성을 설정하고 두 서비스를 모두 시작한 다음 sv1
, sv2
마지막으로 sva
통신 CPU에서 열려 있는 모든 UDP 포트에서 서비스를 수동으로 다시 시작하면 상태 저장 NAT 구성이 적용됩니다. . 그러나 기본적으로 이러한 서비스 시작 시퀀스는 산업용 장비에서 수행될 수 없습니다. 애플리케이션 서비스는 sva
통신 서비스가 통신할 준비가 되었는지 여부와 독립적으로 실행되어야 합니다.
대상 포트의 개방 상태와 관계없이 두 개의 UDP 채널에 대해 상태 비저장 NAT를 갖기 위해 필요한 명령(체인/규칙)은 무엇이며, 어떤 서비스가 UDP 패킷을 다른 서비스에 먼저 전송 0.0.0.5:53404 - 0.0.0.17:50404
합니까 ?0.0.0.5:53441 - 0.0.0.17:50441
추신: 서비스는 sv2
장치 구성에 따라 시작될 수도 있고, NAT 및 네트워크 네임스페이스 없이 전역 네임스페이스에서 다른 물리적 네트워크 어댑터를 사용할 수도 있습니다. 이 네트워크 구성에서는 세 서비스 간의 UDP 통신에 전혀 문제가 없습니다.
답변1
여러 시간에 걸쳐 문서, 튜토리얼, 다양한 웹 페이지에 대한 조언, 많은 실험, 심층적이고 포괄적인 네트워크 및 넷필터 모니터링 및 분석을 읽은 후 마침내 솔루션을 직접 찾았습니다.
nft add table ip prot1
nft add chain ip prot1 prerouting '{ type filter hook prerouting priority -300; policy accept; }'
nft add rule ip prot1 prerouting iif enp1s0 udp dport '{ 50404, 50441 }' ip daddr set 0.0.0.17 notrack accept
nft add rule ip prot1 prerouting iif vprot0 ip saddr 0.0.0.17 notrack accept
nft add chain ip prot1 postrouting '{ type filter hook postrouting priority 100; policy accept; }'
nft add rule ip prot1 postrouting oif enp1s0 ip saddr 0.0.0.17 ip saddr set 0.0.0.6 accept
이것웹 필터 후크다음 지침을 이해하려면 먼저 페이지를 열고 읽어야 합니다.
명령 사용 지침:
- ㅏ웹 필터 테이블
ip
(IPv4) 라는 프로토콜에 추가되었습니다prot1
. - ㅏ체인우선순위로 후크 유형 이름 테이블에 추가됩니다
prot1
. 연결 추적을 우회하려면 이보다 낮은 우선순위 번호를 사용하는 것이 중요합니다. 이는 우선순위가 낮은 대상 네트워크 주소 변환 유형 체인을 사용하는 것을 배제합니다.prerouting
filter
prerouting
-300
-200
conntrack
nat
- ㅏ필터 규칙프로토콜 유형 또는 의 입력 인터페이스 에서 수신된 IPv4 패킷에만 적용
prot1
되는 테이블 체인에 추가되어 패킷의 대상을 에서 로 변경하고 이 UDP 패킷에 대한 연결을 활성화합니다. 실제로 통신 CPU의 서비스를 위해 애플리케이션 CPU의 서비스에서 수신한 UDP 패킷을 가능한 한 빨리 다음 후크(이 경우 후크)로 전달할 필요는 없지만 결정은 명시적으로 지정됩니다.prerouting
i
i
f
enp1s0
udp
d
port
50404
50441
ip
d
addr
0.0.0.6
0.0.0.17
no track
accept
sva
sv2
forward
- 일초필터 규칙
prot1
체인에 테이블에 추가prerouting
, 다음에만 적용됩니다.모두i
프로토콜 유형(,,...)에 관계없이 입력 인터페이스에서 수신된 IPv4 패킷은i
패킷을 활성화한 연결의 출처를 갖습니다. 물론 적절한 소스 또는 대상 포트 번호를 사용하여 UDP 패킷만 필터링하는 것이 가능하지만 이 추가 제한은 여기에서 필요하지 않으며 이 규칙은 서비스에 따라 아직 열려 있지 않은 대상 포트에서 다시 전송되는 ICMP 패킷에도 적용됩니다. 현재는 실행되지 않습니다. 암시적 기본값을 사용하는 대신 명시적으로 판정을 다시 지정하면 패킷이 가능한 한 빨리 후크에 전달됩니다.f
vprot0
udp
icmp
ip
s
addr
0.0.0.17
no track
0.0.0.17
0.0.0.5
sv2
accept
continue
forward
- 일초체인우선순위로 후크 유형 이름 테이블에 추가됩니다
prot1
. 연결 추적을 우회하는 UDP(및 ICMP) 패킷에 소스 주소 변환을 적용하려면 유형 체인 대신 유형 체인을 사용하는 것이 중요합니다.postrouting
filter
postrouting
100
filter
nat
- ㅏ필터 규칙ess에서 패킷의 출처를 수정하는 소스를 사용하여 프로토콜 유형(,, ...)에 관계없이 출력 인터페이스에서 전송된 IPv4 패킷 에만 적용되는
prot1
두 번째 체인을 테이블 에 추가합니다 . 통신 CPU의 서비스에서 수신된 UDP 패킷은 실제로 가능한 한 빨리 응용 CPU의 서비스로 전달될 필요는 없지만 이 결정은 다시 명시적으로 지정됩니다. 또한 이 규칙은 서비스가 아직 실행되지 않아 연결할 수 없는 대상 포트로 전송된 ICMP 패킷의 소스 주소를 변경합니다. 따라서 애플리케이션 CPU는 두 UDP 채널의 통신에 서로 다른 인터페이스를 사용한다는 사실을 결코 인식하지 못합니다. 이는 중요하지는 않지만 충족해야 할 두 번째 요구 사항입니다.postrouting
o
i
f
enp1s0
udp
icmp
s
addr
0.0.0.17
ip
s
addr
0.0.0.17
0.0.0.6
accept
sv2
sva
0.0.0.6
0.0.0.17
sv2
0.0.0.6
매우 구체적인 네트워크 구성과 무상태 네트워크 변환이 필요한 서비스 간 통신 유형 sva
과 sv2
수행해야 하는 NAT를 검색하는 것은 어려운 작업입니다.아니요후크를 사용하세요 nat
.
답변2
귀하의 기사에 진심으로 감사드립니다. 나에게 많은 도움이되었습니다.
팁 하나 더: 설정을 하는 중인데 작동하지 않으면 "conntrack -L"을 사용하여 contrack에서 기존 연결을 확인하고 "conntrack -D"를 사용하여 삭제하세요.
이는 내 구성에서 프로브를 검색하는 데 몇 시간을 소비했기 때문입니다. 문제는 없지만 이전 연결은 여전히 사용할 수 있습니다.