@@ -29,6 +29,8 @@ import (
29
29
"github.com/Jigsaw-Code/outline-ss-server/service/metrics"
30
30
ss "github.com/Jigsaw-Code/outline-ss-server/shadowsocks"
31
31
logging "github.com/op/go-logging"
32
+ "github.com/stretchr/testify/assert"
33
+ "github.com/stretchr/testify/require"
32
34
)
33
35
34
36
const maxUDPPacketSize = 64 * 1024
@@ -162,6 +164,65 @@ func TestTCPEcho(t *testing.T) {
162
164
echoRunning .Wait ()
163
165
}
164
166
167
+ type statusMetrics struct {
168
+ metrics.NoOpMetrics
169
+ sync.Mutex
170
+ statuses []string
171
+ }
172
+
173
+ func (m * statusMetrics ) AddClosedTCPConnection (clientLocation , accessKey , status string , data metrics.ProxyMetrics , timeToCipher , duration time.Duration ) {
174
+ m .Lock ()
175
+ m .statuses = append (m .statuses , status )
176
+ m .Unlock ()
177
+ }
178
+
179
+ func TestRestrictedAddresses (t * testing.T ) {
180
+ proxyListener , err := net .ListenTCP ("tcp" , & net.TCPAddr {IP : net .ParseIP ("127.0.0.1" ), Port : 0 })
181
+ require .NoError (t , err , "ListenTCP failed: %v" , err )
182
+ secrets := ss .MakeTestSecrets (1 )
183
+ cipherList , err := service .MakeTestCiphers (secrets )
184
+ require .NoError (t , err )
185
+ const testTimeout = 200 * time .Millisecond
186
+ testMetrics := & statusMetrics {}
187
+ proxy := service .NewTCPService (cipherList , nil , testMetrics , testTimeout )
188
+ go proxy .Serve (proxyListener )
189
+
190
+ proxyHost , proxyPort , err := net .SplitHostPort (proxyListener .Addr ().String ())
191
+ require .NoError (t , err )
192
+ portNum , err := strconv .Atoi (proxyPort )
193
+ require .NoError (t , err )
194
+ client , err := client .NewClient (proxyHost , portNum , secrets [0 ], ss .TestCipher )
195
+ require .NoError (t , err , "Failed to create ShadowsocksClient" )
196
+
197
+ buf := make ([]byte , 10 )
198
+
199
+ addresses := []string {
200
+ "localhost:9999" ,
201
+ "[::1]:80" ,
202
+ "10.0.0.1:1234" ,
203
+ "[fc00::1]:54321" ,
204
+ }
205
+
206
+ expectedStatus := []string {
207
+ "ERR_ADDRESS_INVALID" ,
208
+ "ERR_ADDRESS_INVALID" ,
209
+ "ERR_ADDRESS_PRIVATE" ,
210
+ "ERR_ADDRESS_PRIVATE" ,
211
+ }
212
+
213
+ for _ , address := range addresses {
214
+ conn , err := client .DialTCP (nil , address )
215
+ require .NoError (t , err , "Failed to dial %v" , address )
216
+ n , err := conn .Read (buf )
217
+ assert .Equal (t , 0 , n , "Server should close without replying on rejected address" )
218
+ assert .Equal (t , io .EOF , err )
219
+ conn .Close ()
220
+ }
221
+
222
+ proxy .GracefulStop ()
223
+ assert .ElementsMatch (t , testMetrics .statuses , expectedStatus )
224
+ }
225
+
165
226
// Metrics about one UDP packet.
166
227
type udpRecord struct {
167
228
location , accessKey , status string
0 commit comments