go-socks5/socks5_test.go

246 lines
5.2 KiB
Go
Raw Normal View History

2014-01-23 22:16:44 +00:00
package socks5
import (
"bytes"
"io"
"log"
2014-01-23 22:16:44 +00:00
"net"
"os"
2014-01-23 22:16:44 +00:00
"testing"
"time"
)
func TestSOCKS5_Connect(t *testing.T) {
// Create a local listener
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("err: %v", err)
}
go func() {
conn, err := l.Accept()
if err != nil {
t.Fatalf("err: %v", err)
}
defer conn.Close()
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(conn, buf, 4); err != nil {
t.Fatalf("err: %v", err)
}
if !bytes.Equal(buf, []byte("ping")) {
t.Fatalf("bad: %v", buf)
}
conn.Write([]byte("pong"))
}()
lAddr := l.Addr().(*net.TCPAddr)
// Create a socks server
2020-04-20 08:19:51 +00:00
cator := UserPassAuthenticator{
Credentials: StaticCredentials{"foo": "bar"},
2014-01-23 22:16:44 +00:00
}
conf := &Config{
AuthMethods: []Authenticator{cator},
2020-04-19 09:47:39 +00:00
Logger: NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags)),
2014-01-23 22:16:44 +00:00
}
serv, err := New(conf)
if err != nil {
t.Fatalf("err: %v", err)
}
// Start listening
go func() {
if err := serv.ListenAndServe("tcp", "127.0.0.1:12365"); err != nil {
t.Fatalf("err: %v", err)
}
}()
time.Sleep(10 * time.Millisecond)
// Get a local conn
conn, err := net.Dial("tcp", "127.0.0.1:12365")
if err != nil {
t.Fatalf("err: %v", err)
}
// Connect, auth and connec to local
2020-04-20 08:19:51 +00:00
req := new(bytes.Buffer)
req.Write([]byte{socks5Version, 2, NoAuth, UserPassAuth})
req.Write([]byte{userPassAuthVersion, 3, 'f', 'o', 'o', 3, 'b', 'a', 'r'})
reqHead := Header{
Version: socks5Version,
Command: ConnectCommand,
Reserved: 0,
Address: AddrSpec{
"",
net.ParseIP("127.0.0.1"),
lAddr.Port,
},
addrType: ipv4Address,
}
req.Write(reqHead.Bytes())
2014-01-23 22:16:44 +00:00
// Send a ping
req.Write([]byte("ping"))
// Send all the bytes
conn.Write(req.Bytes())
// Verify response
expected := []byte{
2020-04-20 08:19:51 +00:00
socks5Version, UserPassAuth, // use user password auth
userPassAuthVersion, authSuccess, // response auth success
2014-01-23 22:16:44 +00:00
}
2020-04-20 08:19:51 +00:00
rspHead := Header{
Version: socks5Version,
Command: successReply,
Reserved: 0,
Address: AddrSpec{
"",
net.ParseIP("127.0.0.1"),
0, // Ignore the port
},
addrType: ipv4Address,
}
expected = append(expected, rspHead.Bytes()...)
expected = append(expected, []byte("pong")...)
2014-01-23 22:16:44 +00:00
out := make([]byte, len(expected))
2020-04-20 08:19:51 +00:00
conn.SetDeadline(time.Now().Add(time.Second))
if _, err := io.ReadFull(conn, out); err != nil {
t.Fatalf("err: %v", err)
}
t.Logf("proxy bind port: %d", buildPort(out[12], out[13]))
// Ignore the port
out[12] = 0
out[13] = 0
if !bytes.Equal(out, expected) {
t.Fatalf("bad: %v", out)
}
}
2014-01-23 22:16:44 +00:00
2020-04-20 08:19:51 +00:00
func TestSOCKS5_Associate(t *testing.T) {
locIP := net.ParseIP("127.0.0.1")
// Create a local listener
lAddr := &net.UDPAddr{
IP: locIP,
Port: 12398,
}
l, err := net.ListenUDP("udp4", lAddr)
if err != nil {
t.Fatalf("err: %v", err)
}
defer l.Close()
go func() {
buf := make([]byte, 2048)
for {
n, remote, err := l.ReadFrom(buf)
if err != nil {
return
}
if !bytes.Equal(buf[:n], []byte("ping")) {
t.Fatalf("bad: %v", buf)
}
l.WriteTo([]byte("pong"), remote)
}
}()
// Create a socks server
cator := UserPassAuthenticator{Credentials: StaticCredentials{"foo": "bar"}}
conf := &Config{
AuthMethods: []Authenticator{cator},
Logger: NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags)),
}
serv, err := New(conf)
if err != nil {
t.Fatalf("err: %v", err)
}
// Start listening
go func() {
if err := serv.ListenAndServe("tcp", "127.0.0.1:12355"); err != nil {
t.Fatalf("err: %v", err)
}
}()
time.Sleep(10 * time.Millisecond)
// Get a local conn
conn, err := net.Dial("tcp", "127.0.0.1:12355")
if err != nil {
t.Fatalf("err: %v", err)
}
// Connect, auth and connec to local
req := new(bytes.Buffer)
req.Write([]byte{socks5Version, 2, NoAuth, UserPassAuth})
req.Write([]byte{userPassAuthVersion, 3, 'f', 'o', 'o', 3, 'b', 'a', 'r'})
reqHead := Header{
Version: socks5Version,
Command: AssociateCommand,
Reserved: 0,
Address: AddrSpec{
"",
locIP,
lAddr.Port,
},
addrType: ipv4Address,
}
req.Write(reqHead.Bytes())
// Send all the bytes
conn.Write(req.Bytes())
// Verify response
expected := []byte{
socks5Version, UserPassAuth, // use user password auth
userPassAuthVersion, authSuccess, // response auth success
}
rspHead := Header{
Version: socks5Version,
Command: successReply,
Reserved: 0,
Address: AddrSpec{
"",
net.ParseIP("0.0.0.0"),
0, // Ignore the port
},
addrType: ipv4Address,
}
expected = append(expected, rspHead.Bytes()...)
out := make([]byte, len(expected))
2014-01-23 22:16:44 +00:00
conn.SetDeadline(time.Now().Add(time.Second))
2020-04-20 08:19:51 +00:00
if _, err := io.ReadFull(conn, out); err != nil {
2014-01-23 22:16:44 +00:00
t.Fatalf("err: %v", err)
}
2014-01-24 22:31:58 +00:00
// Ignore the port
2020-04-20 08:19:51 +00:00
proxyBindPort := buildPort(out[12], out[13])
2014-01-24 22:31:58 +00:00
out[12] = 0
out[13] = 0
2020-04-20 08:19:51 +00:00
t.Logf("proxy bind listen port: %d", proxyBindPort)
2014-01-23 22:16:44 +00:00
if !bytes.Equal(out, expected) {
t.Fatalf("bad: %v", out)
}
2020-04-20 08:19:51 +00:00
udpConn, err := net.DialUDP("udp4", nil, &net.UDPAddr{
IP: locIP,
//Port: lAddr.Port,
Port: proxyBindPort,
})
if err != nil {
t.Fatalf("bad dial: %v", err)
}
// Send a ping
udpConn.Write([]byte("ping"))
response := make([]byte, 1024)
n, _, err := udpConn.ReadFrom(response)
if !bytes.Equal(response[:n], []byte("pong")) {
t.Fatalf("bad udp read: %v", string(response[:n]))
}
time.Sleep(time.Second * 1)
2014-01-23 22:16:44 +00:00
}