Skip to content

Commit

Permalink
add shadowsocks
Browse files Browse the repository at this point in the history
  • Loading branch information
sloweax committed Jan 14, 2025
1 parent 16adc06 commit 29661f9
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@ set key "v a l u e" | socks5 127.0.0.1:1234 user 'my password'

- socks5 / socks5h
- socks4 / socks4a
- ss (shadowsocks)
11 changes: 10 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@ module github.com/sloweax/sockx

go 1.19

require github.com/sloweax/argparse v0.0.0-20241113001422-2d1c5ee3c102
require (
github.com/shadowsocks/go-shadowsocks2 v0.1.5
github.com/sloweax/argparse v0.1.0
)

require (
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect
)
17 changes: 15 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
github.com/sloweax/argparse v0.0.0-20241113001422-2d1c5ee3c102 h1:ybDRocc1hXRco/6a0jozEMm/6AJx1TUm59V/WHUlNpk=
github.com/sloweax/argparse v0.0.0-20241113001422-2d1c5ee3c102/go.mod h1:N3Js6gWN6Be5Qgw143ULfhaTk8oZvrg/QxbrjKREq+Q=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/shadowsocks/go-shadowsocks2 v0.1.5 h1:PDSQv9y2S85Fl7VBeOMF9StzeXZyK1HakRm86CUbr28=
github.com/shadowsocks/go-shadowsocks2 v0.1.5/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM=
github.com/sloweax/argparse v0.1.0 h1:7tzlOj2eFNAtaH8qKsca5VJPAALdd2Wg8IkvuGAJWr4=
github.com/sloweax/argparse v0.1.0/go.mod h1:N3Js6gWN6Be5Qgw143ULfhaTk8oZvrg/QxbrjKREq+Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
31 changes: 30 additions & 1 deletion proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net"
"strings"

"github.com/sloweax/sockx/proxy/shadowsocks"
"github.com/sloweax/sockx/proxy/socks4"
"github.com/sloweax/sockx/proxy/socks5"
)
Expand Down Expand Up @@ -37,6 +38,8 @@ type ProxyDialer interface {

func (p *ProxyInfo) ToDialer() (ProxyDialer, error) {
switch p.Protocol {
case "ss":
return p.ToShadowSocks()
case "socks5", "socks5h":
return p.ToSOCKS5()
case "socks4", "socks4a":
Expand All @@ -60,6 +63,33 @@ func (p *ProxyInfo) ToSOCKS4() (ProxyDialer, error) {
return socks4.NewDialer("tcp", p.Address, p.KWArgs, config), nil
}

func (p *ProxyInfo) ToShadowSocks() (ProxyDialer, error) {
network := "tcp"
password := ""
method := "chacha20-ietf-poly1305"
switch len(p.Args) {
default:
return nil, fmt.Errorf("%s: invalid proxy options", p.Protocol)
case 2:
password = p.Args[1]
fallthrough
case 1:
method = p.Args[0]
case 0:
}

if strings.Contains(p.Address, "/") {
network = "unix"
}

dialer, err := shadowsocks.NewDialer(network, p.Address, p.KWArgs, method, password)
if err != nil {
return nil, err
}

return dialer, nil
}

func (p *ProxyInfo) ToSOCKS5() (ProxyDialer, error) {
config := socks5.Config{}
config.Methods = append(config.Methods, socks5.MethodNoAuth)
Expand All @@ -84,7 +114,6 @@ func (p *ProxyInfo) ToSOCKS5() (ProxyDialer, error) {
config.Methods = append(config.Methods, socks5.MethodUserPass)
return socks5.NewDialer(network, p.Address, p.KWArgs, config), nil
}

}

func (p *ProxyInfo) String() string {
Expand Down
81 changes: 81 additions & 0 deletions proxy/shadowsocks/proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package shadowsocks

import (
"context"
"fmt"
"net"

"github.com/shadowsocks/go-shadowsocks2/core"
"github.com/shadowsocks/go-shadowsocks2/socks"
)

type Dialer struct {
cipher core.Cipher
kwargs map[string]string
network string
address string
}

func (s *Dialer) Protocol() string {
return "ss"
}

func (s *Dialer) KWArgs() map[string]string {
return s.kwargs
}

func (s *Dialer) Network() string {
return s.network
}

func (s *Dialer) String() string {
return s.address
}

func (s *Dialer) DialContextWithConn(ctx context.Context, conn net.Conn, network, addr string) (net.Conn, error) {
type result struct {
net.Conn
error
}

target := socks.ParseAddr(addr)
if target == nil {
return nil, fmt.Errorf("failed to parse address %q", addr)
}

c := make(chan result, 1)
defer close(c)

go func() {
conn = s.cipher.StreamConn(conn)
if _, err := conn.Write(target); err != nil {
conn.Close()
c <- result{error: err}
} else {
c <- result{Conn: conn}
}
}()

select {
case <-ctx.Done():
conn.Close()
return nil, ctx.Err()
case r := <-c:
return r.Conn, r.error
}
}

func NewDialer(network, address string, kwargs map[string]string, method, password string) (*Dialer, error) {
d := new(Dialer)
d.network = network
d.address = address
d.kwargs = kwargs

cipher, err := core.PickCipher(method, nil, password)
if err != nil {
return nil, err
}
d.cipher = cipher

return d, nil
}

0 comments on commit 29661f9

Please sign in to comment.