Browse Source

Feature: socks5 over unix domain socket(UDS) support

this feature is compatible with tor proxy.
pull/76/head
xjasonlyu 3 years ago
parent
commit
07ce5e6422
  1. 23
      engine/parse.go
  2. 16
      proxy/socks5.go

23
engine/parse.go

@ -51,11 +51,11 @@ func parseProxy(s string) (proxy.Proxy, error) {
case proto.Reject.String():
return proxy.NewReject(), nil
case proto.HTTP.String():
return proxy.NewHTTP(parseAddrUserPass(u))
return proxy.NewHTTP(parseHTTP(u))
case proto.Socks4.String():
return proxy.NewSocks4(parseAddrUser(u))
return proxy.NewSocks4(parseSocks4(u))
case proto.Socks5.String():
return proxy.NewSocks5(parseAddrUserPass(u))
return proxy.NewSocks5(parseSocks5(u))
case proto.Shadowsocks.String():
return proxy.NewShadowsocks(parseShadowsocks(u))
default:
@ -63,14 +63,25 @@ func parseProxy(s string) (proxy.Proxy, error) {
}
}
func parseAddrUser(u *url.URL) (address, username string) {
func parseHTTP(u *url.URL) (address, username, password string) {
address, username = u.Host, u.User.Username()
password, _ = u.User.Password()
return
}
func parseSocks4(u *url.URL) (address, username string) {
address, username = u.Host, u.User.Username()
return
}
func parseAddrUserPass(u *url.URL) (address, username, password string) {
address, username = parseAddrUser(u)
func parseSocks5(u *url.URL) (address, username, password string) {
address, username = u.Host, u.User.Username()
password, _ = u.User.Password()
// Socks5 over UDS
if address == "" {
address = u.Path
}
return
}

16
proxy/socks5.go

@ -2,6 +2,7 @@ package proxy
import (
"context"
"errors"
"fmt"
"io"
"net"
@ -19,6 +20,9 @@ type Socks5 struct {
user string
pass string
// unix indicates if socks5 over UDS is enabled.
unix bool
}
func NewSocks5(addr, user, pass string) (*Socks5, error) {
@ -29,11 +33,17 @@ func NewSocks5(addr, user, pass string) (*Socks5, error) {
},
user: user,
pass: pass,
unix: len(addr) > 0 && addr[0] == '/',
}, nil
}
func (ss *Socks5) DialContext(ctx context.Context, metadata *M.Metadata) (c net.Conn, err error) {
c, err = dialer.DialContext(ctx, "tcp", ss.Addr())
var network = "tcp"
if ss.unix {
network = "unix"
}
c, err = dialer.DialContext(ctx, network, ss.Addr())
if err != nil {
return nil, fmt.Errorf("connect to %s: %w", ss.Addr(), err)
}
@ -54,6 +64,10 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *M.Metadata) (c net.
}
func (ss *Socks5) DialUDP(*M.Metadata) (_ net.PacketConn, err error) {
if ss.unix {
return nil, errors.New("not supported when unix domain socket is enabled")
}
ctx, cancel := context.WithTimeout(context.Background(), tcpConnectTimeout)
defer cancel()

Loading…
Cancel
Save