mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 18:24:02 +03:00
FILE / ScuroNeko/mtg
mtglib/network/shadowsocks.go
Исходный файл и его история в репозитории.
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package network
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
shadowsocks "github.com/shadowsocks/go-shadowsocks2/core"
|
|
"golang.org/x/net/proxy"
|
|
)
|
|
|
|
type shadowsocksDialer struct {
|
|
Dialer
|
|
|
|
cipher shadowsocks.StreamConnCipher
|
|
}
|
|
|
|
func (s *shadowsocksDialer) Dial(network, address string) (net.Conn, error) {
|
|
return s.DialContext(context.Background(), network, address)
|
|
}
|
|
|
|
func (s *shadowsocksDialer) DialContext(ctx context.Context,
|
|
network, address string) (net.Conn, error) {
|
|
conn, err := s.Dialer.DialContext(ctx, network, address)
|
|
if err != nil {
|
|
return nil, err // nolint: wrapcheck
|
|
}
|
|
|
|
return s.cipher.StreamConn(conn), nil
|
|
}
|
|
|
|
func NewShadowsocksDialer(proxyURL *url.URL,
|
|
timeout time.Duration, bufferSize int) (Dialer, error) {
|
|
username := proxyURL.User.Username()
|
|
|
|
decoded, err := base64.RawURLEncoding.DecodeString(username)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot decode payload: %w", err)
|
|
}
|
|
|
|
chunks := strings.SplitN(string(decoded), ":", 2)
|
|
if len(chunks) != 2 {
|
|
return nil, fmt.Errorf("incorrect payload %s", username)
|
|
}
|
|
|
|
cipher, err := shadowsocks.PickCipher(chunks[0], nil, chunks[1])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot initialize shadowsocks cipher: %w", err)
|
|
}
|
|
|
|
socks5URL := *proxyURL
|
|
socks5URL.Scheme = "socks5"
|
|
socks5URL.User = nil
|
|
|
|
dialer, err := NewDefaultDialer(timeout, bufferSize)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot initialize a base dialer: %w", err)
|
|
}
|
|
|
|
ssDialer := &shadowsocksDialer{
|
|
Dialer: dialer,
|
|
cipher: cipher,
|
|
}
|
|
|
|
rv, err := proxy.FromURL(&socks5URL, ssDialer)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot initialize ss proxy dialer: %w", err)
|
|
}
|
|
|
|
return rv.(Dialer), nil
|
|
}
|