166 lines
3.9 KiB
Go
166 lines
3.9 KiB
Go
|
|
package socks5
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"net"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestReply(t *testing.T) {
|
||
|
|
tests := []struct {
|
||
|
|
status byte
|
||
|
|
expected []byte
|
||
|
|
}{
|
||
|
|
{ReplySucc, []byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0}},
|
||
|
|
{ReplyFail, []byte{0x05, 0x05, 0x00, 0x01, 0, 0, 0, 0, 0, 0}},
|
||
|
|
{ReplyHostUn, []byte{0x05, 0x07, 0x00, 0x01, 0, 0, 0, 0, 0, 0}},
|
||
|
|
{ReplyNetUn, []byte{0x05, 0x08, 0x00, 0x01, 0, 0, 0, 0, 0, 0}},
|
||
|
|
{0xFF, []byte{0x05, 0xFF, 0x00, 0x01, 0, 0, 0, 0, 0, 0}},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tt := range tests {
|
||
|
|
result := Reply(tt.status)
|
||
|
|
if !bytes.Equal(result, tt.expected) {
|
||
|
|
t.Errorf("Reply(0x%02X) = %v, expected %v", tt.status, result, tt.expected)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestHandleGreeting_Success(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send valid greeting with no-auth method
|
||
|
|
go client.Write([]byte{0x05, 0x01, 0x00})
|
||
|
|
|
||
|
|
nmethods, err := HandleGreeting(server)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("HandleGreeting failed: %v", err)
|
||
|
|
}
|
||
|
|
if nmethods != 1 {
|
||
|
|
t.Errorf("Expected 1 method, got %d", nmethods)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Read response
|
||
|
|
buf := make([]byte, 2)
|
||
|
|
server.Read(buf)
|
||
|
|
if !bytes.Equal(buf, []byte{0x05, 0x00}) {
|
||
|
|
t.Errorf("Expected accept response, got %v", buf)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestHandleGreeting_UnsupportedVersion(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send SOCKS4 greeting
|
||
|
|
go client.Write([]byte{0x04, 0x01, 0x00})
|
||
|
|
|
||
|
|
_, err := HandleGreeting(server)
|
||
|
|
if err != ErrUnsupportedVersion {
|
||
|
|
t.Errorf("Expected ErrUnsupportedVersion, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestHandleGreeting_NoAuthNotSupported(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send greeting without no-auth method
|
||
|
|
go client.Write([]byte{0x05, 0x01, 0x01})
|
||
|
|
|
||
|
|
_, err := HandleGreeting(server)
|
||
|
|
if err != ErrNoAuthAccepted {
|
||
|
|
t.Errorf("Expected ErrNoAuthAccepted, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestReadRequest_IPv4(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send CONNECT request for IPv4
|
||
|
|
// ver=5, cmd=1, rsv=0, atyp=1, addr=127.0.0.1, port=8080
|
||
|
|
go client.Write([]byte{
|
||
|
|
0x05, 0x01, 0x00, 0x01,
|
||
|
|
127, 0, 0, 1,
|
||
|
|
0x1F, 0x90, // port 8080
|
||
|
|
})
|
||
|
|
|
||
|
|
req, err := ReadRequest(server)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("ReadRequest failed: %v", err)
|
||
|
|
}
|
||
|
|
if req.DestAddr != "127.0.0.1" {
|
||
|
|
t.Errorf("Expected addr 127.0.0.1, got %s", req.DestAddr)
|
||
|
|
}
|
||
|
|
if req.DestPort != 8080 {
|
||
|
|
t.Errorf("Expected port 8080, got %d", req.DestPort)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestReadRequest_Domain(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send CONNECT request for domain
|
||
|
|
// ver=5, cmd=1, rsv=0, atyp=3, len=9, domain=example.com, port=80
|
||
|
|
go client.Write([]byte{
|
||
|
|
0x05, 0x01, 0x00, 0x03,
|
||
|
|
0x0B, // length of "example.com"
|
||
|
|
})
|
||
|
|
go client.Write([]byte("example.com"))
|
||
|
|
go client.Write([]byte{0x00, 0x50}) // port 80
|
||
|
|
|
||
|
|
req, err := ReadRequest(server)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("ReadRequest failed: %v", err)
|
||
|
|
}
|
||
|
|
if req.DestAddr != "example.com" {
|
||
|
|
t.Errorf("Expected addr example.com, got %s", req.DestAddr)
|
||
|
|
}
|
||
|
|
if req.DestPort != 80 {
|
||
|
|
t.Errorf("Expected port 80, got %d", req.DestPort)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestReadRequest_IPv6(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send CONNECT request for IPv6 ::1
|
||
|
|
go client.Write([]byte{
|
||
|
|
0x05, 0x01, 0x00, 0x04,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||
|
|
0x00, 0x50, // port 80
|
||
|
|
})
|
||
|
|
|
||
|
|
req, err := ReadRequest(server)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("ReadRequest failed: %v", err)
|
||
|
|
}
|
||
|
|
if req.DestAddr != "::1" {
|
||
|
|
t.Errorf("Expected addr ::1, got %s", req.DestAddr)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestReadRequest_UnsupportedCmd(t *testing.T) {
|
||
|
|
client, server := net.Pipe()
|
||
|
|
defer client.Close()
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
// Send UDP ASSOCIATE request
|
||
|
|
go client.Write([]byte{0x05, 0x03, 0x00, 0x01, 127, 0, 0, 1, 0, 80})
|
||
|
|
|
||
|
|
_, err := ReadRequest(server)
|
||
|
|
if err != ErrUnsupportedCmd {
|
||
|
|
t.Errorf("Expected ErrUnsupportedCmd, got %v", err)
|
||
|
|
}
|
||
|
|
}
|