@@ -22,8 +22,11 @@ import (
22
22
"testing"
23
23
"time"
24
24
25
+ onet "github.com/Jigsaw-Code/outline-ss-server/net"
26
+ "github.com/Jigsaw-Code/outline-ss-server/service/metrics"
25
27
ss "github.com/Jigsaw-Code/outline-ss-server/shadowsocks"
26
28
logging "github.com/op/go-logging"
29
+ "github.com/shadowsocks/go-shadowsocks2/socks"
27
30
)
28
31
29
32
const timeout = 5 * time .Minute
@@ -86,6 +89,77 @@ func (conn *fakePacketConn) Close() error {
86
89
return nil
87
90
}
88
91
92
+ // Stub metrics implementation for testing NAT behaviors.
93
+ type natTestMetrics struct {
94
+ metrics.ShadowsocksMetrics
95
+ natEntriesAdded int
96
+ }
97
+
98
+ func (m * natTestMetrics ) AddTCPProbe (clientLocation , status , drainResult string , port int , data metrics.ProxyMetrics ) {
99
+ }
100
+ func (m * natTestMetrics ) AddClosedTCPConnection (clientLocation , accessKey , status string , data metrics.ProxyMetrics , timeToCipher , duration time.Duration ) {
101
+ }
102
+ func (m * natTestMetrics ) GetLocation (net.Addr ) (string , error ) {
103
+ return "" , nil
104
+ }
105
+ func (m * natTestMetrics ) SetNumAccessKeys (numKeys int , numPorts int ) {
106
+ }
107
+ func (m * natTestMetrics ) AddOpenTCPConnection (clientLocation string ) {
108
+ }
109
+ func (m * natTestMetrics ) AddUDPPacketFromClient (clientLocation , accessKey , status string , clientProxyBytes , proxyTargetBytes int , timeToCipher time.Duration ) {
110
+ }
111
+ func (m * natTestMetrics ) AddUDPPacketFromTarget (clientLocation , accessKey , status string , targetProxyBytes , proxyClientBytes int ) {
112
+ }
113
+ func (m * natTestMetrics ) AddUDPNatEntry () {
114
+ m .natEntriesAdded ++
115
+ }
116
+ func (m * natTestMetrics ) RemoveUDPNatEntry () {}
117
+
118
+ func TestIPFilter (t * testing.T ) {
119
+ // Takes a validation policy, and returns the metrics it
120
+ // generates when localhost access is attempted
121
+ checkLocalhost := func (validator onet.TargetIPValidator ) * natTestMetrics {
122
+ ciphers , _ := MakeTestCiphers ([]string {"asdf" })
123
+ cipher := ciphers .SnapshotForClientIP (nil )[0 ].Value .(* CipherEntry ).Cipher
124
+ clientConn := makePacketConn ()
125
+ metrics := & natTestMetrics {}
126
+ service := NewUDPService (timeout , ciphers , metrics )
127
+ service .SetTargetIPValidator (validator )
128
+ go service .Serve (clientConn )
129
+
130
+ // Send one packet to the "discard" port on localhost
131
+ targetAddr := socks .ParseAddr ("127.0.0.1:9" )
132
+ payload := []byte ("payload" )
133
+ plaintext := append (targetAddr , payload ... )
134
+ ciphertext := make ([]byte , cipher .SaltSize ()+ len (plaintext )+ cipher .TagSize ())
135
+ ss .Pack (ciphertext , plaintext , cipher )
136
+ clientConn .recv <- packet {
137
+ addr : & net.UDPAddr {
138
+ IP : net .ParseIP ("192.0.2.1" ),
139
+ Port : 54321 ,
140
+ },
141
+ payload : ciphertext ,
142
+ }
143
+
144
+ service .GracefulStop ()
145
+ return metrics
146
+ }
147
+
148
+ t .Run ("Localhost allowed" , func (t * testing.T ) {
149
+ metrics := checkLocalhost (allowAll )
150
+ if metrics .natEntriesAdded != 1 {
151
+ t .Errorf ("Expected 1 NAT entry, not %d" , metrics .natEntriesAdded )
152
+ }
153
+ })
154
+
155
+ t .Run ("Localhost not allowed" , func (t * testing.T ) {
156
+ metrics := checkLocalhost (onet .RequirePublicIP )
157
+ if metrics .natEntriesAdded != 0 {
158
+ t .Error ("Unexpected NAT entry on rejected packet" )
159
+ }
160
+ })
161
+ }
162
+
89
163
func assertAlmostEqual (t * testing.T , a , b time.Time ) {
90
164
delta := a .Sub (b )
91
165
limit := 100 * time .Millisecond
@@ -95,14 +169,14 @@ func assertAlmostEqual(t *testing.T, a, b time.Time) {
95
169
}
96
170
97
171
func TestNATEmpty (t * testing.T ) {
98
- nat := newNATmap (timeout , & probeTestMetrics {}, & sync.WaitGroup {})
172
+ nat := newNATmap (timeout , & natTestMetrics {}, & sync.WaitGroup {})
99
173
if nat .Get ("foo" ) != nil {
100
174
t .Error ("Expected nil value from empty NAT map" )
101
175
}
102
176
}
103
177
104
- func setup () (* fakePacketConn , * fakePacketConn , * natconn ) {
105
- nat := newNATmap (timeout , & probeTestMetrics {}, & sync.WaitGroup {})
178
+ func setupNAT () (* fakePacketConn , * fakePacketConn , * natconn ) {
179
+ nat := newNATmap (timeout , & natTestMetrics {}, & sync.WaitGroup {})
106
180
clientConn := makePacketConn ()
107
181
targetConn := makePacketConn ()
108
182
nat .Add (& clientAddr , clientConn , natCipher , targetConn , "ZZ" , "key id" )
@@ -111,7 +185,7 @@ func setup() (*fakePacketConn, *fakePacketConn, *natconn) {
111
185
}
112
186
113
187
func TestNATGet (t * testing.T ) {
114
- _ , targetConn , entry := setup ()
188
+ _ , targetConn , entry := setupNAT ()
115
189
if entry == nil {
116
190
t .Fatal ("Failed to find target conn" )
117
191
}
@@ -121,7 +195,7 @@ func TestNATGet(t *testing.T) {
121
195
}
122
196
123
197
func TestNATWrite (t * testing.T ) {
124
- _ , targetConn , entry := setup ()
198
+ _ , targetConn , entry := setupNAT ()
125
199
126
200
// Simulate one generic packet being sent
127
201
buf := []byte {1 }
@@ -137,7 +211,7 @@ func TestNATWrite(t *testing.T) {
137
211
}
138
212
139
213
func TestNATWriteDNS (t * testing.T ) {
140
- _ , targetConn , entry := setup ()
214
+ _ , targetConn , entry := setupNAT ()
141
215
142
216
// Simulate one DNS query being sent.
143
217
buf := []byte {1 }
@@ -154,7 +228,7 @@ func TestNATWriteDNS(t *testing.T) {
154
228
}
155
229
156
230
func TestNATWriteDNSMultiple (t * testing.T ) {
157
- _ , targetConn , entry := setup ()
231
+ _ , targetConn , entry := setupNAT ()
158
232
159
233
// Simulate three DNS queries being sent.
160
234
buf := []byte {1 }
@@ -169,7 +243,7 @@ func TestNATWriteDNSMultiple(t *testing.T) {
169
243
}
170
244
171
245
func TestNATWriteMixed (t * testing.T ) {
172
- _ , targetConn , entry := setup ()
246
+ _ , targetConn , entry := setupNAT ()
173
247
174
248
// Simulate both non-DNS and DNS packets being sent.
175
249
buf := []byte {1 }
@@ -182,7 +256,7 @@ func TestNATWriteMixed(t *testing.T) {
182
256
}
183
257
184
258
func TestNATFastClose (t * testing.T ) {
185
- clientConn , targetConn , entry := setup ()
259
+ clientConn , targetConn , entry := setupNAT ()
186
260
187
261
// Send one DNS query.
188
262
query := []byte {1 }
@@ -208,7 +282,7 @@ func TestNATFastClose(t *testing.T) {
208
282
}
209
283
210
284
func TestNATNoFastClose_NotDNS (t * testing.T ) {
211
- clientConn , targetConn , entry := setup ()
285
+ clientConn , targetConn , entry := setupNAT ()
212
286
213
287
// Send one non-DNS packet.
214
288
query := []byte {1 }
@@ -233,7 +307,7 @@ func TestNATNoFastClose_NotDNS(t *testing.T) {
233
307
}
234
308
235
309
func TestNATNoFastClose_MultipleDNS (t * testing.T ) {
236
- clientConn , targetConn , entry := setup ()
310
+ clientConn , targetConn , entry := setupNAT ()
237
311
238
312
// Send two DNS packets.
239
313
query1 := []byte {1 }
@@ -267,7 +341,7 @@ func (e *fakeTimeoutError) Temporary() bool {
267
341
}
268
342
269
343
func TestNATTimeout (t * testing.T ) {
270
- _ , targetConn , entry := setup ()
344
+ _ , targetConn , entry := setupNAT ()
271
345
272
346
// Simulate a non-DNS initial packet.
273
347
entry .WriteTo ([]byte {1 }, & targetAddr )
@@ -365,7 +439,7 @@ func TestUDPDoubleServe(t *testing.T) {
365
439
if err != nil {
366
440
t .Fatal (err )
367
441
}
368
- testMetrics := & probeTestMetrics {}
442
+ testMetrics := & natTestMetrics {}
369
443
const testTimeout = 200 * time .Millisecond
370
444
s := NewUDPService (testTimeout , cipherList , testMetrics )
371
445
@@ -399,7 +473,7 @@ func TestUDPEarlyStop(t *testing.T) {
399
473
if err != nil {
400
474
t .Fatal (err )
401
475
}
402
- testMetrics := & probeTestMetrics {}
476
+ testMetrics := & natTestMetrics {}
403
477
const testTimeout = 200 * time .Millisecond
404
478
s := NewUDPService (testTimeout , cipherList , testMetrics )
405
479
0 commit comments