mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 07:42:38 +08:00 
			
		
		
		
	ssr: add ssr support
This commit is contained in:
		
							parent
							
								
									d4a1d59d31
								
							
						
					
					
						commit
						2e6ab5767a
					
				@ -48,6 +48,8 @@ func DialerFromURL(s string, dialer Dialer) (Dialer, error) {
 | 
			
		||||
		return NewSOCKS5(addr, user, pass, dialer)
 | 
			
		||||
	case "ss":
 | 
			
		||||
		return NewSS(addr, user, pass, dialer)
 | 
			
		||||
	case "ssr":
 | 
			
		||||
		return NewSSR(addr, user, pass, u.RawQuery, dialer)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, errors.New("unknown schema '" + u.Scheme + "'")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								http.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								http.go
									
									
									
									
									
								
							@ -69,7 +69,7 @@ func (s *HTTP) ListenAndServe() {
 | 
			
		||||
	for {
 | 
			
		||||
		c, err := l.Accept()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logf("failed to accept: %v", err)
 | 
			
		||||
			logf("proxy-http failed to accept: %v", err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -130,7 +130,7 @@ func (s *HTTP) Serve(c net.Conn) {
 | 
			
		||||
	rc, err := s.dialer.Dial("tcp", tgt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto)
 | 
			
		||||
		logf("failed to dial: %v", err)
 | 
			
		||||
		logf("proxy-http failed to dial: %v", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer rc.Close()
 | 
			
		||||
@ -164,7 +164,7 @@ func (s *HTTP) Serve(c net.Conn) {
 | 
			
		||||
 | 
			
		||||
	respHeader, err := respTP.ReadMIMEHeader()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logf("read header error:%s", err)
 | 
			
		||||
		logf("proxy-http read header error:%s", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -191,7 +191,7 @@ func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.Write([]byte(proto))
 | 
			
		||||
		c.Write([]byte(" 502 ERROR\r\n\r\n"))
 | 
			
		||||
		logf("failed to dial: %v", err)
 | 
			
		||||
		logf("proxy-http failed to dial: %v", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -218,7 +218,7 @@ func (s *HTTP) NextDialer(dstAddr string) Dialer { return s.dialer.NextDialer(ds
 | 
			
		||||
func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
 | 
			
		||||
	rc, err := s.dialer.Dial(network, s.addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logf("dial to %s error: %s", s.addr, err)
 | 
			
		||||
		logf("proxy-http dial to %s error: %s", s.addr, err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -261,7 +261,7 @@ func parseFirstLine(tp *textproto.Reader) (r1, r2, r3 string, ok bool) {
 | 
			
		||||
	line, err := tp.ReadLine()
 | 
			
		||||
	// logf("first line: %s", line)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logf("read request line error:%s", err)
 | 
			
		||||
		logf("proxy-http read request line error:%s", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								ss.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								ss.go
									
									
									
									
									
								
							@ -210,7 +210,7 @@ func (s *SS) NextDialer(dstAddr string) Dialer { return s.dialer.NextDialer(dstA
 | 
			
		||||
func (s *SS) Dial(network, addr string) (net.Conn, error) {
 | 
			
		||||
	target := ParseAddr(addr)
 | 
			
		||||
	if target == nil {
 | 
			
		||||
		return nil, errors.New("Unable to parse address: " + addr)
 | 
			
		||||
		return nil, errors.New("proxy-ss unable to parse address: " + addr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if network == "uot" {
 | 
			
		||||
@ -219,7 +219,7 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) {
 | 
			
		||||
 | 
			
		||||
	c, err := s.dialer.Dial("tcp", s.addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logf("dial to %s error: %s", s.addr, err)
 | 
			
		||||
		logf("proxy-ss dial to %s error: %s", s.addr, err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										132
									
								
								ssr.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								ssr.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,132 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	shadowsocksr "github.com/sun8911879/shadowsocksR"
 | 
			
		||||
	"github.com/sun8911879/shadowsocksR/obfs"
 | 
			
		||||
	"github.com/sun8911879/shadowsocksR/protocol"
 | 
			
		||||
	"github.com/sun8911879/shadowsocksR/ssr"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SSR .
 | 
			
		||||
type SSR struct {
 | 
			
		||||
	dialer Dialer
 | 
			
		||||
	addr   string
 | 
			
		||||
 | 
			
		||||
	EncryptMethod   string
 | 
			
		||||
	EncryptPassword string
 | 
			
		||||
	Obfs            string
 | 
			
		||||
	ObfsParam       string
 | 
			
		||||
	ObfsData        interface{}
 | 
			
		||||
	Protocol        string
 | 
			
		||||
	ProtocolParam   string
 | 
			
		||||
	ProtocolData    interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSSR returns a shadowsocksr proxy, ssr://method:pass@host:port/rawQuery
 | 
			
		||||
func NewSSR(addr, method, pass, rawQuery string, dialer Dialer) (*SSR, error) {
 | 
			
		||||
	s := &SSR{
 | 
			
		||||
		dialer:          dialer,
 | 
			
		||||
		addr:            addr,
 | 
			
		||||
		EncryptMethod:   method,
 | 
			
		||||
		EncryptPassword: pass,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p, _ := url.ParseQuery(rawQuery)
 | 
			
		||||
	if v, ok := p["protocol"]; ok {
 | 
			
		||||
		s.Protocol = v[0]
 | 
			
		||||
	}
 | 
			
		||||
	if v, ok := p["protocol_param"]; ok {
 | 
			
		||||
		s.ProtocolParam = v[0]
 | 
			
		||||
	}
 | 
			
		||||
	if v, ok := p["obfs"]; ok {
 | 
			
		||||
		s.Obfs = v[0]
 | 
			
		||||
	}
 | 
			
		||||
	if v, ok := p["obfs_param"]; ok {
 | 
			
		||||
		s.ObfsParam = v[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Addr returns forwarder's address
 | 
			
		||||
func (s *SSR) Addr() string { return s.addr }
 | 
			
		||||
 | 
			
		||||
// NextDialer returns the next dialer
 | 
			
		||||
func (s *SSR) NextDialer(dstAddr string) Dialer { return s.dialer.NextDialer(dstAddr) }
 | 
			
		||||
 | 
			
		||||
// Dial connects to the address addr on the network net via the proxy.
 | 
			
		||||
func (s *SSR) Dial(network, addr string) (net.Conn, error) {
 | 
			
		||||
	target := ParseAddr(addr)
 | 
			
		||||
	if target == nil {
 | 
			
		||||
		return nil, errors.New("proxy-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 {
 | 
			
		||||
		logf("proxy-ssr dial to %s error: %s", s.addr, err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c, ok := c.(*net.TCPConn); ok {
 | 
			
		||||
		c.SetKeepAlive(true)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
 | 
			
		||||
	if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil {
 | 
			
		||||
		return nil, errors.New("proxy-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)
 | 
			
		||||
	obfsServerInfo := &ssr.ServerInfoForObfs{
 | 
			
		||||
		Host:   rs[0],
 | 
			
		||||
		Port:   uint16(port),
 | 
			
		||||
		TcpMss: 1460,
 | 
			
		||||
		Param:  s.ObfsParam,
 | 
			
		||||
	}
 | 
			
		||||
	ssrconn.IObfs.SetServerInfo(obfsServerInfo)
 | 
			
		||||
	ssrconn.IProtocol = protocol.NewProtocol(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 connects to the given address via the proxy.
 | 
			
		||||
func (s *SSR) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
 | 
			
		||||
	return nil, nil, errors.New("proxy-ssr udp not supported now")
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user