@@ -10,9 +10,8 @@ import (
1010 "github.com/netbirdio/netbird/client/iface/device"
1111)
1212
13- // TestStatefulNATBidirectionalSSH tests that stateful NAT prevents interference
14- // when two peers try to SSH to each other simultaneously
15- func TestStatefulNATBidirectionalSSH (t * testing.T ) {
13+ // TestPortDNATBasic tests basic port DNAT functionality
14+ func TestPortDNATBasic (t * testing.T ) {
1615 manager , err := Create (& IFaceMock {
1716 SetFilterFunc : func (device.PacketFilter ) error { return nil },
1817 }, false , flowLogger )
@@ -30,46 +29,25 @@ func TestStatefulNATBidirectionalSSH(t *testing.T) {
3029 require .NoError (t , err )
3130
3231 // Scenario: Peer A connects to Peer B on port 22 (should get NAT)
33- // This simulates: ssh [email protected] 3432 packetAtoB := generateDNATTestPacket (t , peerA , peerB , layers .IPProtocolTCP , 54321 , 22 )
35- translatedAtoB := manager .translateInboundPortDNAT (packetAtoB , parsePacket (t , packetAtoB ))
33+ d := parsePacket (t , packetAtoB )
34+ translatedAtoB := manager .translateInboundPortDNAT (packetAtoB , d , peerA , peerB )
3635 require .True (t , translatedAtoB , "Peer A to Peer B should be translated (NAT applied)" )
3736
3837 // Verify port was translated to 22022
39- d : = parsePacket (t , packetAtoB )
38+ d = parsePacket (t , packetAtoB )
4039 require .Equal (t , uint16 (22022 ), uint16 (d .tcp .DstPort ), "Port should be rewritten to 22022" )
4140
42- // Verify NAT connection is tracked (with translated port as key)
43- natConn , exists := manager .portNATTracker .getConnectionNAT (peerA , peerB , 54321 , 22022 )
44- require .True (t , exists , "NAT connection should be tracked" )
45- require .Equal (t , uint16 (22 ), natConn .originalPort , "Original port should be stored" )
46-
47- // Scenario: Peer B tries to connect to Peer A on port 22 (should NOT get NAT)
48- // This simulates the reverse direction to prevent interference
49- packetBtoA := generateDNATTestPacket (t , peerB , peerA , layers .IPProtocolTCP , 54322 , 22 )
50- translatedBtoA := manager .translateInboundPortDNAT (packetBtoA , parsePacket (t , packetBtoA ))
51- require .False (t , translatedBtoA , "Peer B to Peer A should NOT be translated (prevent interference)" )
52-
53- // Verify port was NOT translated
54- d2 := parsePacket (t , packetBtoA )
55- require .Equal (t , uint16 (22 ), uint16 (d2 .tcp .DstPort ), "Port should remain 22 (no translation)" )
56-
57- // Verify no reverse NAT connection is tracked
58- _ , reverseExists := manager .portNATTracker .getConnectionNAT (peerB , peerA , 54322 , 22 )
59- require .False (t , reverseExists , "Reverse NAT connection should NOT be tracked" )
60-
61- // Scenario: Return traffic from Peer B (SSH server) to Peer A (should be reverse translated)
41+ // Scenario: Return traffic from Peer B to Peer A should NOT be translated
42+ // (prevents double NAT - original port stored in conntrack)
6243 returnPacket := generateDNATTestPacket (t , peerB , peerA , layers .IPProtocolTCP , 22022 , 54321 )
63- translatedReturn := manager .translateOutboundPortReverse (returnPacket , parsePacket (t , returnPacket ))
64- require .True (t , translatedReturn , "Return traffic should be reverse translated" )
65-
66- // Verify return traffic port was translated back to 22
67- d3 := parsePacket (t , returnPacket )
68- require .Equal (t , uint16 (22 ), uint16 (d3 .tcp .SrcPort ), "Return traffic source port should be 22" )
44+ d2 := parsePacket (t , returnPacket )
45+ translatedReturn := manager .translateInboundPortDNAT (returnPacket , d2 , peerB , peerA )
46+ require .False (t , translatedReturn , "Return traffic from same IP should not be translated" )
6947}
7048
71- // TestStatefulNATConnectionCleanup tests connection cleanup functionality
72- func TestStatefulNATConnectionCleanup (t * testing.T ) {
49+ // TestPortDNATMultipleRules tests multiple port DNAT rules
50+ func TestPortDNATMultipleRules (t * testing.T ) {
7351 manager , err := Create (& IFaceMock {
7452 SetFilterFunc : func (device.PacketFilter ) error { return nil },
7553 }, false , flowLogger )
@@ -88,24 +66,19 @@ func TestStatefulNATConnectionCleanup(t *testing.T) {
8866 err = manager .addPortRedirection (peerB , layers .LayerTypeTCP , 22 , 22022 )
8967 require .NoError (t , err )
9068
91- // Establish connection with NAT
92- packet := generateDNATTestPacket (t , peerA , peerB , layers .IPProtocolTCP , 54321 , 22 )
93- translated := manager .translateInboundPortDNAT (packet , parsePacket (t , packet ))
94- require .True (t , translated , "Initial connection should be translated" )
95-
96- // Verify connection is tracked (using translated port as key)
97- _ , exists := manager .portNATTracker .getConnectionNAT (peerA , peerB , 54321 , 22022 )
98- require .True (t , exists , "Connection should be tracked" )
99-
100- // Clean up connection
101- manager .portNATTracker .cleanupConnection (peerA , peerB , 54321 )
102-
103- // Verify connection is no longer tracked (using translated port as key)
104- _ , stillExists := manager .portNATTracker .getConnectionNAT (peerA , peerB , 54321 , 22022 )
105- require .False (t , stillExists , "Connection should be cleaned up" )
106-
107- // Verify new connection from opposite direction now works
108- reversePacket := generateDNATTestPacket (t , peerB , peerA , layers .IPProtocolTCP , 54322 , 22 )
109- reverseTranslated := manager .translateInboundPortDNAT (reversePacket , parsePacket (t , reversePacket ))
110- require .True (t , reverseTranslated , "Reverse connection should now work after cleanup" )
69+ // Test traffic to peer B gets translated
70+ packetToB := generateDNATTestPacket (t , peerA , peerB , layers .IPProtocolTCP , 54321 , 22 )
71+ d1 := parsePacket (t , packetToB )
72+ translatedToB := manager .translateInboundPortDNAT (packetToB , d1 , peerA , peerB )
73+ require .True (t , translatedToB , "Traffic to peer B should be translated" )
74+ d1 = parsePacket (t , packetToB )
75+ require .Equal (t , uint16 (22022 ), uint16 (d1 .tcp .DstPort ), "Port should be 22022" )
76+
77+ // Test traffic to peer A gets translated
78+ packetToA := generateDNATTestPacket (t , peerB , peerA , layers .IPProtocolTCP , 54322 , 22 )
79+ d2 := parsePacket (t , packetToA )
80+ translatedToA := manager .translateInboundPortDNAT (packetToA , d2 , peerB , peerA )
81+ require .True (t , translatedToA , "Traffic to peer A should be translated" )
82+ d2 = parsePacket (t , packetToA )
83+ require .Equal (t , uint16 (22022 ), uint16 (d2 .tcp .DstPort ), "Port should be 22022" )
11184}
0 commit comments