socks5 support

This commit is contained in:
Luxferre
2026-09-01 11:02:25 +03:00
parent 21731e4d8d
commit 9a8e7af831
3 changed files with 112 additions and 2 deletions
+80
View File
@@ -7,6 +7,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"net/http/httptest"
"os"
@@ -2199,3 +2200,82 @@ func TestFilterTextPrintableOnly(t *testing.T) {
t.Errorf("filterText = %q, want %q", got, "ok\t\nab")
}
}
func TestProxyFromEnv(t *testing.T) {
os.Unsetenv("SOCKS_PROXY")
os.Unsetenv("socks_proxy")
req, _ := http.NewRequest("GET", "http://example.com", nil)
_, err := proxyFromEnv(req)
if err != nil {
t.Fatalf("proxyFromEnv err: %v", err)
}
os.Setenv("SOCKS_PROXY", "127.0.0.1:1080")
defer os.Unsetenv("SOCKS_PROXY")
u, err := proxyFromEnv(req)
if err != nil {
t.Fatalf("proxyFromEnv with 127.0.0.1:1080: %v", err)
}
if u == nil || u.Scheme != "socks5" || u.Host != "127.0.0.1:1080" {
t.Fatalf("unexpected url: %v", u)
}
os.Setenv("SOCKS_PROXY", "socks5://localhost:9050")
u, err = proxyFromEnv(req)
if err != nil {
t.Fatalf("proxyFromEnv with socks5://: %v", err)
}
if u == nil || u.Scheme != "socks5" || u.Host != "localhost:9050" {
t.Fatalf("unexpected url: %v", u)
}
os.Unsetenv("SOCKS_PROXY")
os.Setenv("socks_proxy", "socks5h://user:pass@127.0.0.1:1080")
defer os.Unsetenv("socks_proxy")
u, err = proxyFromEnv(req)
if err != nil {
t.Fatalf("proxyFromEnv with socks_proxy: %v", err)
}
if u == nil || u.Scheme != "socks5h" || u.User.Username() != "user" {
t.Fatalf("unexpected url: %v", u)
}
}
func TestSOCKS5ProxySupport(t *testing.T) {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("listen: %v", err)
}
defer l.Close()
handshakeDone := make(chan bool, 1)
go func() {
conn, err := l.Accept()
if err != nil {
return
}
defer conn.Close()
buf := make([]byte, 256)
n, err := conn.Read(buf)
if err == nil && n >= 2 && buf[0] == 0x05 {
conn.Write([]byte{0x05, 0x00})
handshakeDone <- true
}
}()
os.Setenv("SOCKS_PROXY", "socks5://"+l.Addr().String())
defer os.Unsetenv("SOCKS_PROXY")
tr := &http.Transport{
Proxy: proxyFromEnv,
DialContext: (&net.Dialer{Timeout: 1 * time.Second}).DialContext,
}
client := &http.Client{Transport: tr, Timeout: 1 * time.Second}
client.Get("http://example.com/test")
select {
case <-handshakeDone:
case <-time.After(2 * time.Second):
t.Fatalf("timed out waiting for SOCKS5 handshake through proxy")
}
}