@@ -89,10 +89,16 @@ func (conn *fakePacketConn) Close() error {
89
89
return nil
90
90
}
91
91
92
+ type udpReport struct {
93
+ clientLocation , accessKey , status string
94
+ clientProxyBytes , proxyTargetBytes int
95
+ }
96
+
92
97
// Stub metrics implementation for testing NAT behaviors.
93
98
type natTestMetrics struct {
94
99
metrics.ShadowsocksMetrics
95
100
natEntriesAdded int
101
+ upstreamPackets []udpReport
96
102
}
97
103
98
104
func (m * natTestMetrics ) AddTCPProbe (clientLocation , status , drainResult string , port int , data metrics.ProxyMetrics ) {
@@ -107,6 +113,7 @@ func (m *natTestMetrics) SetNumAccessKeys(numKeys int, numPorts int) {
107
113
func (m * natTestMetrics ) AddOpenTCPConnection (clientLocation string ) {
108
114
}
109
115
func (m * natTestMetrics ) AddUDPPacketFromClient (clientLocation , accessKey , status string , clientProxyBytes , proxyTargetBytes int , timeToCipher time.Duration ) {
116
+ m .upstreamPackets = append (m .upstreamPackets , udpReport {clientLocation , accessKey , status , clientProxyBytes , proxyTargetBytes })
110
117
}
111
118
func (m * natTestMetrics ) AddUDPPacketFromTarget (clientLocation , accessKey , status string , targetProxyBytes , proxyClientBytes int ) {
112
119
}
@@ -115,21 +122,20 @@ func (m *natTestMetrics) AddUDPNatEntry() {
115
122
}
116
123
func (m * natTestMetrics ) RemoveUDPNatEntry () {}
117
124
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" )
125
+ // Takes a validation policy, and returns the metrics it
126
+ // generates when localhost access is attempted
127
+ func sendToDiscard (payloads [][]byte , validator onet.TargetIPValidator ) * natTestMetrics {
128
+ ciphers , _ := MakeTestCiphers ([]string {"asdf" })
129
+ cipher := ciphers .SnapshotForClientIP (nil )[0 ].Value .(* CipherEntry ).Cipher
130
+ clientConn := makePacketConn ()
131
+ metrics := & natTestMetrics {}
132
+ service := NewUDPService (timeout , ciphers , metrics )
133
+ service .SetTargetIPValidator (validator )
134
+ go service .Serve (clientConn )
135
+
136
+ // Send one packet to the "discard" port on localhost
137
+ targetAddr := socks .ParseAddr ("127.0.0.1:9" )
138
+ for _ , payload := range payloads {
133
139
plaintext := append (targetAddr , payload ... )
134
140
ciphertext := make ([]byte , cipher .SaltSize ()+ len (plaintext )+ cipher .TagSize ())
135
141
ss .Pack (ciphertext , plaintext , cipher )
@@ -140,26 +146,74 @@ func TestIPFilter(t *testing.T) {
140
146
},
141
147
payload : ciphertext ,
142
148
}
143
-
144
- service .GracefulStop ()
145
- return metrics
146
149
}
147
150
151
+ service .GracefulStop ()
152
+ return metrics
153
+ }
154
+
155
+ func TestIPFilter (t * testing.T ) {
156
+ // Test both the first-packet and subsequent-packet cases.
157
+ payloads := [][]byte {[]byte ("payload1" ), []byte ("payload2" )}
158
+
148
159
t .Run ("Localhost allowed" , func (t * testing.T ) {
149
- metrics := checkLocalhost ( allowAll )
160
+ metrics := sendToDiscard ( payloads , allowAll )
150
161
if metrics .natEntriesAdded != 1 {
151
162
t .Errorf ("Expected 1 NAT entry, not %d" , metrics .natEntriesAdded )
152
163
}
153
164
})
154
165
155
166
t .Run ("Localhost not allowed" , func (t * testing.T ) {
156
- metrics := checkLocalhost ( onet .RequirePublicIP )
167
+ metrics := sendToDiscard ( payloads , onet .RequirePublicIP )
157
168
if metrics .natEntriesAdded != 0 {
158
169
t .Error ("Unexpected NAT entry on rejected packet" )
159
170
}
171
+ if len (metrics .upstreamPackets ) != 2 {
172
+ t .Errorf ("Expected 2 reports, not %v" , metrics .upstreamPackets )
173
+ }
174
+ for _ , report := range metrics .upstreamPackets {
175
+ if report .clientProxyBytes == 0 {
176
+ t .Error ("Expected nonzero input packet size" )
177
+ }
178
+ if report .proxyTargetBytes != 0 {
179
+ t .Error ("No bytes should be sent due to a disallowed packet" )
180
+ }
181
+ if report .accessKey != "id-0" {
182
+ t .Errorf ("Unexpected access key: %s" , report .accessKey )
183
+ }
184
+ }
160
185
})
161
186
}
162
187
188
+ func TestUpstreamMetrics (t * testing.T ) {
189
+ // Test both the first-packet and subsequent-packet cases.
190
+ const N = 10
191
+ payloads := make ([][]byte , 0 )
192
+ for i := 1 ; i <= N ; i ++ {
193
+ payloads = append (payloads , make ([]byte , i ))
194
+ }
195
+
196
+ metrics := sendToDiscard (payloads , allowAll )
197
+
198
+ if len (metrics .upstreamPackets ) != N {
199
+ t .Errorf ("Expected %d reports, not %v" , N , metrics .upstreamPackets )
200
+ }
201
+ for i , report := range metrics .upstreamPackets {
202
+ if report .proxyTargetBytes != i + 1 {
203
+ t .Errorf ("Expected %d payload bytes, not %d" , i , report .proxyTargetBytes )
204
+ }
205
+ if report .clientProxyBytes <= report .proxyTargetBytes {
206
+ t .Errorf ("Expected nonzero input overhead (%d > %d)" , report .clientProxyBytes , report .proxyTargetBytes )
207
+ }
208
+ if report .accessKey != "id-0" {
209
+ t .Errorf ("Unexpected access key name: %s" , report .accessKey )
210
+ }
211
+ if report .status != "OK" {
212
+ t .Errorf ("Wrong status: %s" , report .status )
213
+ }
214
+ }
215
+ }
216
+
163
217
func assertAlmostEqual (t * testing.T , a , b time.Time ) {
164
218
delta := a .Sub (b )
165
219
limit := 100 * time .Millisecond
0 commit comments