@@ -22,8 +22,11 @@ import (
2222 "testing"
2323 "time"
2424
25+ onet "github.com/Jigsaw-Code/outline-ss-server/net"
26+ "github.com/Jigsaw-Code/outline-ss-server/service/metrics"
2527 ss "github.com/Jigsaw-Code/outline-ss-server/shadowsocks"
2628 logging "github.com/op/go-logging"
29+ "github.com/shadowsocks/go-shadowsocks2/socks"
2730)
2831
2932const timeout = 5 * time .Minute
@@ -86,6 +89,77 @@ func (conn *fakePacketConn) Close() error {
8689 return nil
8790}
8891
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+
89163func assertAlmostEqual (t * testing.T , a , b time.Time ) {
90164 delta := a .Sub (b )
91165 limit := 100 * time .Millisecond
@@ -95,14 +169,14 @@ func assertAlmostEqual(t *testing.T, a, b time.Time) {
95169}
96170
97171func TestNATEmpty (t * testing.T ) {
98- nat := newNATmap (timeout , & probeTestMetrics {}, & sync.WaitGroup {})
172+ nat := newNATmap (timeout , & natTestMetrics {}, & sync.WaitGroup {})
99173 if nat .Get ("foo" ) != nil {
100174 t .Error ("Expected nil value from empty NAT map" )
101175 }
102176}
103177
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 {})
106180 clientConn := makePacketConn ()
107181 targetConn := makePacketConn ()
108182 nat .Add (& clientAddr , clientConn , natCipher , targetConn , "ZZ" , "key id" )
@@ -111,7 +185,7 @@ func setup() (*fakePacketConn, *fakePacketConn, *natconn) {
111185}
112186
113187func TestNATGet (t * testing.T ) {
114- _ , targetConn , entry := setup ()
188+ _ , targetConn , entry := setupNAT ()
115189 if entry == nil {
116190 t .Fatal ("Failed to find target conn" )
117191 }
@@ -121,7 +195,7 @@ func TestNATGet(t *testing.T) {
121195}
122196
123197func TestNATWrite (t * testing.T ) {
124- _ , targetConn , entry := setup ()
198+ _ , targetConn , entry := setupNAT ()
125199
126200 // Simulate one generic packet being sent
127201 buf := []byte {1 }
@@ -137,7 +211,7 @@ func TestNATWrite(t *testing.T) {
137211}
138212
139213func TestNATWriteDNS (t * testing.T ) {
140- _ , targetConn , entry := setup ()
214+ _ , targetConn , entry := setupNAT ()
141215
142216 // Simulate one DNS query being sent.
143217 buf := []byte {1 }
@@ -154,7 +228,7 @@ func TestNATWriteDNS(t *testing.T) {
154228}
155229
156230func TestNATWriteDNSMultiple (t * testing.T ) {
157- _ , targetConn , entry := setup ()
231+ _ , targetConn , entry := setupNAT ()
158232
159233 // Simulate three DNS queries being sent.
160234 buf := []byte {1 }
@@ -169,7 +243,7 @@ func TestNATWriteDNSMultiple(t *testing.T) {
169243}
170244
171245func TestNATWriteMixed (t * testing.T ) {
172- _ , targetConn , entry := setup ()
246+ _ , targetConn , entry := setupNAT ()
173247
174248 // Simulate both non-DNS and DNS packets being sent.
175249 buf := []byte {1 }
@@ -182,7 +256,7 @@ func TestNATWriteMixed(t *testing.T) {
182256}
183257
184258func TestNATFastClose (t * testing.T ) {
185- clientConn , targetConn , entry := setup ()
259+ clientConn , targetConn , entry := setupNAT ()
186260
187261 // Send one DNS query.
188262 query := []byte {1 }
@@ -208,7 +282,7 @@ func TestNATFastClose(t *testing.T) {
208282}
209283
210284func TestNATNoFastClose_NotDNS (t * testing.T ) {
211- clientConn , targetConn , entry := setup ()
285+ clientConn , targetConn , entry := setupNAT ()
212286
213287 // Send one non-DNS packet.
214288 query := []byte {1 }
@@ -233,7 +307,7 @@ func TestNATNoFastClose_NotDNS(t *testing.T) {
233307}
234308
235309func TestNATNoFastClose_MultipleDNS (t * testing.T ) {
236- clientConn , targetConn , entry := setup ()
310+ clientConn , targetConn , entry := setupNAT ()
237311
238312 // Send two DNS packets.
239313 query1 := []byte {1 }
@@ -267,7 +341,7 @@ func (e *fakeTimeoutError) Temporary() bool {
267341}
268342
269343func TestNATTimeout (t * testing.T ) {
270- _ , targetConn , entry := setup ()
344+ _ , targetConn , entry := setupNAT ()
271345
272346 // Simulate a non-DNS initial packet.
273347 entry .WriteTo ([]byte {1 }, & targetAddr )
@@ -365,7 +439,7 @@ func TestUDPDoubleServe(t *testing.T) {
365439 if err != nil {
366440 t .Fatal (err )
367441 }
368- testMetrics := & probeTestMetrics {}
442+ testMetrics := & natTestMetrics {}
369443 const testTimeout = 200 * time .Millisecond
370444 s := NewUDPService (testTimeout , cipherList , testMetrics )
371445
@@ -399,7 +473,7 @@ func TestUDPEarlyStop(t *testing.T) {
399473 if err != nil {
400474 t .Fatal (err )
401475 }
402- testMetrics := & probeTestMetrics {}
476+ testMetrics := & natTestMetrics {}
403477 const testTimeout = 200 * time .Millisecond
404478 s := NewUDPService (testTimeout , cipherList , testMetrics )
405479
0 commit comments