mirror of
https://github.com/nadoo/glider.git
synced 2025-02-24 01:45:39 +08:00
131 lines
3.0 KiB
Go
131 lines
3.0 KiB
Go
package ssr
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
|
|
shadowsocksr "github.com/sun8911879/shadowsocksR"
|
|
"github.com/sun8911879/shadowsocksR/obfs"
|
|
"github.com/sun8911879/shadowsocksR/protocol"
|
|
"github.com/sun8911879/shadowsocksR/ssr"
|
|
|
|
"github.com/nadoo/glider/common/log"
|
|
"github.com/nadoo/glider/common/socks"
|
|
"github.com/nadoo/glider/proxy"
|
|
)
|
|
|
|
func init() {
|
|
proxy.RegisterDialer("ssr", CreateDialer)
|
|
}
|
|
|
|
// Dialer struct
|
|
type Dialer struct {
|
|
*SSR
|
|
dialer proxy.Dialer
|
|
}
|
|
|
|
// NewDialer returns a proxy dialer
|
|
func NewDialer(s string, dialer proxy.Dialer) (*Dialer, error) {
|
|
h, err := NewSSR(s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
d := &Dialer{SSR: h, dialer: dialer}
|
|
return d, nil
|
|
}
|
|
|
|
// CreateDialer returns a proxy dialer
|
|
func CreateDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
|
return NewDialer(s, dialer)
|
|
}
|
|
|
|
// Addr returns dialer's address
|
|
func (s *Dialer) Addr() string {
|
|
if s.addr == "" {
|
|
return s.dialer.Addr()
|
|
}
|
|
return s.addr
|
|
}
|
|
|
|
// NextDialer returns the next dialer
|
|
func (s *Dialer) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
|
|
// Dial establishes a connection to the addr
|
|
func (s *Dialer) Dial(network, addr string) (net.Conn, error) {
|
|
target := socks.ParseAddr(addr)
|
|
if target == nil {
|
|
return nil, errors.New("[ssr] unable to parse address: " + addr)
|
|
}
|
|
|
|
cipher, err := shadowsocksr.NewStreamCipher(s.EncryptMethod, s.EncryptPassword)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c, err := s.dialer.Dial("tcp", s.addr)
|
|
if err != nil {
|
|
log.F("[ssr] dial to %s error: %s", s.addr, err)
|
|
return nil, err
|
|
}
|
|
|
|
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
|
|
if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil {
|
|
return nil, errors.New("[ssr] nil connection")
|
|
}
|
|
|
|
// should initialize obfs/protocol now
|
|
rs := strings.Split(ssrconn.RemoteAddr().String(), ":")
|
|
port, _ := strconv.Atoi(rs[1])
|
|
|
|
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
|
|
if ssrconn.IObfs == nil {
|
|
return nil, errors.New("[ssr] unsupported obfs type: " + s.Obfs)
|
|
}
|
|
|
|
obfsServerInfo := &ssr.ServerInfoForObfs{
|
|
Host: rs[0],
|
|
Port: uint16(port),
|
|
TcpMss: 1460,
|
|
Param: s.ObfsParam,
|
|
}
|
|
ssrconn.IObfs.SetServerInfo(obfsServerInfo)
|
|
|
|
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
|
|
if ssrconn.IProtocol == nil {
|
|
return nil, errors.New("[ssr] unsupported protocol type: " + s.Protocol)
|
|
}
|
|
|
|
protocolServerInfo := &ssr.ServerInfoForObfs{
|
|
Host: rs[0],
|
|
Port: uint16(port),
|
|
TcpMss: 1460,
|
|
Param: s.ProtocolParam,
|
|
}
|
|
ssrconn.IProtocol.SetServerInfo(protocolServerInfo)
|
|
|
|
if s.ObfsData == nil {
|
|
s.ObfsData = ssrconn.IObfs.GetData()
|
|
}
|
|
ssrconn.IObfs.SetData(s.ObfsData)
|
|
|
|
if s.ProtocolData == nil {
|
|
s.ProtocolData = ssrconn.IProtocol.GetData()
|
|
}
|
|
ssrconn.IProtocol.SetData(s.ProtocolData)
|
|
|
|
if _, err := ssrconn.Write(target); err != nil {
|
|
ssrconn.Close()
|
|
return nil, err
|
|
}
|
|
|
|
return ssrconn, err
|
|
}
|
|
|
|
// DialUDP returns a PacketConn to the addr
|
|
func (s *Dialer) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
|
|
return nil, nil, errors.New("[ssr] udp not supported now")
|
|
}
|