mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 15:52:38 +08:00 
			
		
		
		
	socks5: support udp in server mode
This commit is contained in:
		
							parent
							
								
									601e0ddcda
								
							
						
					
					
						commit
						6b4d2582ca
					
				@ -21,7 +21,7 @@ Listen(local proxy server):
 | 
				
			|||||||
- SS proxy
 | 
					- SS proxy
 | 
				
			||||||
- Linux transparent proxy(iptables redirect)
 | 
					- Linux transparent proxy(iptables redirect)
 | 
				
			||||||
- TCP tunnel
 | 
					- TCP tunnel
 | 
				
			||||||
- DNS Tunnel(udp2tcp)
 | 
					- UDP over TCP tunnel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Forward(upstream proxy server):
 | 
					Forward(upstream proxy server):
 | 
				
			||||||
- Socks5 proxy
 | 
					- Socks5 proxy
 | 
				
			||||||
@ -47,7 +47,9 @@ General:
 | 
				
			|||||||
- Rule proxy based on destinations: [Config Examples](config/examples)
 | 
					- Rule proxy based on destinations: [Config Examples](config/examples)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TODO:
 | 
					TODO:
 | 
				
			||||||
- [x] UDP over TCP Tunnel (client <--udp--> glider/uottun <--tcp--> ss <--udp--> target)
 | 
					
 | 
				
			||||||
 | 
					- [x] UDP tunnel
 | 
				
			||||||
 | 
					- [x] UDP over TCP Tunnel (client <--udp--> glider/uottun <--tcp--> glider/ss <--udp--> target)
 | 
				
			||||||
- [ ] Transparent UDP proxy (iptables tproxy)
 | 
					- [ ] Transparent UDP proxy (iptables tproxy)
 | 
				
			||||||
- [ ] DNS Cache
 | 
					- [ ] DNS Cache
 | 
				
			||||||
- [ ] TUN/TAP device support
 | 
					- [ ] TUN/TAP device support
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								http.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								http.go
									
									
									
									
									
								
							@ -249,7 +249,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// DialUDP connects to the given address via the proxy.
 | 
					// DialUDP connects to the given address via the proxy.
 | 
				
			||||||
func (s *HTTP) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
 | 
					func (s *HTTP) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
 | 
				
			||||||
	return nil, nil, errors.New("DialUDP not supported")
 | 
						return nil, nil, errors.New("http client does not support udp")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
 | 
					// parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										15
									
								
								mixed.go
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								mixed.go
									
									
									
									
									
								
							@ -41,18 +41,21 @@ func NewMixedProxy(addr, user, pass, rawQuery string, sDialer Dialer) (*MixedPro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ListenAndServe .
 | 
					// ListenAndServe .
 | 
				
			||||||
func (p *MixedProxy) ListenAndServe() {
 | 
					func (p *MixedProxy) ListenAndServe() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go p.socks5.ListenAndServeUDP()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l, err := net.Listen("tcp", p.addr)
 | 
						l, err := net.Listen("tcp", p.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("failed to listen on %s: %v", p.addr, err)
 | 
							logf("proxy-mixed failed to listen on %s: %v", p.addr, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logf("listening TCP on %s", p.addr)
 | 
						logf("proxy-mixed listening TCP on %s", p.addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		c, err := l.Accept()
 | 
							c, err := l.Accept()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			logf("failed to accept: %v", err)
 | 
								logf("proxy-mixed failed to accept: %v", err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,13 +76,13 @@ func (p *MixedProxy) Serve(conn net.Conn) {
 | 
				
			|||||||
	if p.socks5 != nil {
 | 
						if p.socks5 != nil {
 | 
				
			||||||
		head, err := c.Peek(1)
 | 
							head, err := c.Peek(1)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			logf("peek error: %s", err)
 | 
								logf("proxy-mixed peek error: %s", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// check socks5, client send socksversion: 5 as the first byte
 | 
							// check socks5, client send socksversion: 5 as the first byte
 | 
				
			||||||
		if head[0] == socks5Version {
 | 
							if head[0] == socks5Version {
 | 
				
			||||||
			p.socks5.Serve(c)
 | 
								p.socks5.ServeTCP(c)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -87,7 +90,7 @@ func (p *MixedProxy) Serve(conn net.Conn) {
 | 
				
			|||||||
	if p.http != nil {
 | 
						if p.http != nil {
 | 
				
			||||||
		head, err := c.Peek(8)
 | 
							head, err := c.Peek(8)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			logf("peek error: %s", err)
 | 
								logf("proxy-mixed peek error: %s", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										196
									
								
								socks5.go
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								socks5.go
									
									
									
									
									
								
							@ -14,6 +14,8 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const socks5Version = 5
 | 
					const socks5Version = 5
 | 
				
			||||||
@ -43,16 +45,17 @@ const MaxAddrLen = 1 + 1 + 255 + 2
 | 
				
			|||||||
// Addr represents a SOCKS address as defined in RFC 1928 section 5.
 | 
					// Addr represents a SOCKS address as defined in RFC 1928 section 5.
 | 
				
			||||||
type Addr []byte
 | 
					type Addr []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var socks5Errors = []string{
 | 
					var socks5Errors = []error{
 | 
				
			||||||
	"",
 | 
						errors.New(""),
 | 
				
			||||||
	"general failure",
 | 
						errors.New("general failure"),
 | 
				
			||||||
	"connection forbidden",
 | 
						errors.New("connection forbidden"),
 | 
				
			||||||
	"network unreachable",
 | 
						errors.New("network unreachable"),
 | 
				
			||||||
	"host unreachable",
 | 
						errors.New("host unreachable"),
 | 
				
			||||||
	"connection refused",
 | 
						errors.New("connection refused"),
 | 
				
			||||||
	"TTL expired",
 | 
						errors.New("TTL expired"),
 | 
				
			||||||
	"command not supported",
 | 
						errors.New("command not supported"),
 | 
				
			||||||
	"address type not supported",
 | 
						errors.New("address type not supported"),
 | 
				
			||||||
 | 
						errors.New("socks5UDPAssociate"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SOCKS5 struct
 | 
					// SOCKS5 struct
 | 
				
			||||||
@ -77,8 +80,14 @@ func NewSOCKS5(addr, user, pass string, cDialer Dialer, sDialer Dialer) (*SOCKS5
 | 
				
			|||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServe .
 | 
					// ListenAndServe serves socks5 requests.
 | 
				
			||||||
func (s *SOCKS5) ListenAndServe() {
 | 
					func (s *SOCKS5) ListenAndServe() {
 | 
				
			||||||
 | 
						go s.ListenAndServeUDP()
 | 
				
			||||||
 | 
						s.ListenAndServeTCP()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServeTCP .
 | 
				
			||||||
 | 
					func (s *SOCKS5) ListenAndServeTCP() {
 | 
				
			||||||
	l, err := net.Listen("tcp", s.addr)
 | 
						l, err := net.Listen("tcp", s.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-socks5 failed to listen on %s: %v", s.addr, err)
 | 
							logf("proxy-socks5 failed to listen on %s: %v", s.addr, err)
 | 
				
			||||||
@ -94,12 +103,12 @@ func (s *SOCKS5) ListenAndServe() {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		go s.Serve(c)
 | 
							go s.ServeTCP(c)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Serve .
 | 
					// ServeTCP .
 | 
				
			||||||
func (s *SOCKS5) Serve(c net.Conn) {
 | 
					func (s *SOCKS5) ServeTCP(c net.Conn) {
 | 
				
			||||||
	defer c.Close()
 | 
						defer c.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c, ok := c.(*net.TCPConn); ok {
 | 
						if c, ok := c.(*net.TCPConn); ok {
 | 
				
			||||||
@ -108,6 +117,20 @@ func (s *SOCKS5) Serve(c net.Conn) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	tgt, err := s.handshake(c)
 | 
						tgt, err := s.handshake(c)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							// UDP: keep the connection until disconnect then free the UDP socket
 | 
				
			||||||
 | 
							if err == socks5Errors[9] {
 | 
				
			||||||
 | 
								buf := []byte{}
 | 
				
			||||||
 | 
								// block here
 | 
				
			||||||
 | 
								for {
 | 
				
			||||||
 | 
									_, err := c.Read(buf)
 | 
				
			||||||
 | 
									if err, ok := err.(net.Error); ok && err.Timeout() {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									logf("UDP Associate End.")
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		logf("proxy-socks5 failed to get target address: %v", err)
 | 
							logf("proxy-socks5 failed to get target address: %v", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -130,6 +153,62 @@ func (s *SOCKS5) Serve(c net.Conn) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServeUDP serves udp requests.
 | 
				
			||||||
 | 
					func (s *SOCKS5) ListenAndServeUDP() {
 | 
				
			||||||
 | 
						lc, err := net.ListenPacket("udp", s.addr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logf("proxy-socks5-udp failed to listen on %s: %v", s.addr, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer lc.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logf("proxy-socks5-udp listening UDP on %s", s.addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var nm sync.Map
 | 
				
			||||||
 | 
						buf := make([]byte, udpBufSize)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							c := NewSocks5PktConn(lc, nil, nil, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							n, raddr, err := c.ReadFrom(buf)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logf("proxy-socks5-udp remote read error: %v", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var pc *Socks5PktConn
 | 
				
			||||||
 | 
							v, ok := nm.Load(raddr.String())
 | 
				
			||||||
 | 
							if !ok && v == nil {
 | 
				
			||||||
 | 
								lpc, nextHop, err := s.sDialer.DialUDP("udp", c.tgtAddr.String())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									logf("proxy-socks5-udp remote dial error: %v", err)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								pc = NewSocks5PktConn(lpc, nextHop, nil, false)
 | 
				
			||||||
 | 
								nm.Store(raddr.String(), pc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								go func() {
 | 
				
			||||||
 | 
									timedCopy(c, raddr, pc, 2*time.Minute)
 | 
				
			||||||
 | 
									pc.Close()
 | 
				
			||||||
 | 
									nm.Delete(raddr.String())
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								pc = v.(*Socks5PktConn)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_, err = pc.WriteTo(buf[:n], pc.writeAddr)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logf("proxy-socks5-udp remote write error: %v", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							logf("proxy-socks5-udp %s <-> %s", raddr, c.tgtAddr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Dial connects to the address addr on the network net via the SOCKS5 proxy.
 | 
					// Dial connects to the address addr on the network net via the SOCKS5 proxy.
 | 
				
			||||||
func (s *SOCKS5) Dial(network, addr string) (net.Conn, error) {
 | 
					func (s *SOCKS5) Dial(network, addr string) (net.Conn, error) {
 | 
				
			||||||
	switch network {
 | 
						switch network {
 | 
				
			||||||
@ -158,7 +237,7 @@ func (s *SOCKS5) Dial(network, addr string) (net.Conn, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// DialUDP connects to the given address via the proxy.
 | 
					// DialUDP connects to the given address via the proxy.
 | 
				
			||||||
func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
 | 
					func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
 | 
				
			||||||
	return nil, nil, errors.New("DialUDP not supported")
 | 
						return nil, nil, errors.New("sock5 client does not support udp now")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// connect takes an existing connection to a socks5 proxy server,
 | 
					// connect takes an existing connection to a socks5 proxy server,
 | 
				
			||||||
@ -254,7 +333,7 @@ func (s *SOCKS5) connect(conn net.Conn, target string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	failure := "unknown error"
 | 
						failure := "unknown error"
 | 
				
			||||||
	if int(buf[1]) < len(socks5Errors) {
 | 
						if int(buf[1]) < len(socks5Errors) {
 | 
				
			||||||
		failure = socks5Errors[buf[1]]
 | 
							failure = socks5Errors[buf[1]].Error()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(failure) > 0 {
 | 
						if len(failure) > 0 {
 | 
				
			||||||
@ -314,16 +393,26 @@ func (s *SOCKS5) handshake(rw io.ReadWriter) (Addr, error) {
 | 
				
			|||||||
	if _, err := io.ReadFull(rw, buf[:3]); err != nil {
 | 
						if _, err := io.ReadFull(rw, buf[:3]); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if buf[1] != socks5Connect {
 | 
						cmd := buf[1]
 | 
				
			||||||
		return nil, errors.New(socks5Errors[7])
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	addr, err := readAddr(rw, buf)
 | 
						addr, err := readAddr(rw, buf)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// write VER REP RSV ATYP BND.ADDR BND.PORT
 | 
						switch cmd {
 | 
				
			||||||
	_, err = rw.Write([]byte{5, 0, 0, 1, 0, 0, 0, 0, 0, 0})
 | 
						case socks5Connect:
 | 
				
			||||||
	return addr, err
 | 
							_, err = rw.Write([]byte{5, 0, 0, 1, 0, 0, 0, 0, 0, 0}) // SOCKS v5, reply succeeded
 | 
				
			||||||
 | 
						case socks5UDPAssociate:
 | 
				
			||||||
 | 
							listenAddr := ParseAddr(rw.(net.Conn).LocalAddr().String())
 | 
				
			||||||
 | 
							_, err = rw.Write(append([]byte{5, 0, 0}, listenAddr...)) // SOCKS v5, reply succeeded
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, socks5Errors[7]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = socks5Errors[9]
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nil, socks5Errors[7]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return addr, err // skip VER, CMD, RSV fields
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// String serializes SOCKS address a to string form.
 | 
					// String serializes SOCKS address a to string form.
 | 
				
			||||||
@ -380,7 +469,7 @@ func readAddr(r io.Reader, b []byte) (Addr, error) {
 | 
				
			|||||||
		return b[:1+net.IPv6len+2], err
 | 
							return b[:1+net.IPv6len+2], err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil, errors.New(socks5Errors[8])
 | 
						return nil, socks5Errors[8]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReadAddr reads just enough bytes from r to get a valid Addr.
 | 
					// ReadAddr reads just enough bytes from r to get a valid Addr.
 | 
				
			||||||
@ -453,3 +542,64 @@ func ParseAddr(s string) Addr {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return addr
 | 
						return addr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Socks5PktConn .
 | 
				
			||||||
 | 
					type Socks5PktConn struct {
 | 
				
			||||||
 | 
						net.PacketConn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writeAddr net.Addr // write to and read from addr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tgtAddr   Addr
 | 
				
			||||||
 | 
						tgtHeader bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewSocks5PktConn returns a Socks5PktConn
 | 
				
			||||||
 | 
					func NewSocks5PktConn(c net.PacketConn, writeAddr net.Addr, tgtAddr Addr, tgtHeader bool) *Socks5PktConn {
 | 
				
			||||||
 | 
						pc := &Socks5PktConn{
 | 
				
			||||||
 | 
							PacketConn: c,
 | 
				
			||||||
 | 
							writeAddr:  writeAddr,
 | 
				
			||||||
 | 
							tgtAddr:    tgtAddr,
 | 
				
			||||||
 | 
							tgtHeader:  tgtHeader}
 | 
				
			||||||
 | 
						return pc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pc *Socks5PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
 | 
				
			||||||
 | 
						if !pc.tgtHeader {
 | 
				
			||||||
 | 
							return pc.PacketConn.ReadFrom(b)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf := make([]byte, len(b))
 | 
				
			||||||
 | 
						n, raddr, err := pc.PacketConn.ReadFrom(buf)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return n, raddr, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// https://tools.ietf.org/html/rfc1928#section-7
 | 
				
			||||||
 | 
						// +----+------+------+----------+----------+----------+
 | 
				
			||||||
 | 
						// |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
 | 
				
			||||||
 | 
						// +----+------+------+----------+----------+----------+
 | 
				
			||||||
 | 
						// | 2  |  1   |  1   | Variable |    2     | Variable |
 | 
				
			||||||
 | 
						// +----+------+------+----------+----------+----------+
 | 
				
			||||||
 | 
						tgtAddr := SplitAddr(buf[3:])
 | 
				
			||||||
 | 
						copy(b, buf[3+len(tgtAddr):])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//test
 | 
				
			||||||
 | 
						if pc.writeAddr == nil {
 | 
				
			||||||
 | 
							pc.writeAddr = raddr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if pc.tgtAddr == nil {
 | 
				
			||||||
 | 
							pc.tgtAddr = tgtAddr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return n - len(tgtAddr), raddr, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (pc *Socks5PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
 | 
				
			||||||
 | 
						if !pc.tgtHeader {
 | 
				
			||||||
 | 
							return pc.PacketConn.WriteTo(b, addr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf := append(append([]byte{0, 0, 0}, b[:]...))
 | 
				
			||||||
 | 
						return pc.PacketConn.WriteTo(buf, pc.writeAddr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								ss.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								ss.go
									
									
									
									
									
								
							@ -243,7 +243,7 @@ func (s *SS) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
 | 
				
			|||||||
	return pkc, nextHop, err
 | 
						return pkc, nextHop, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PktConn wraps a net.PacketConn and support Write method like net.Conn
 | 
					// PktConn .
 | 
				
			||||||
type PktConn struct {
 | 
					type PktConn struct {
 | 
				
			||||||
	net.PacketConn
 | 
						net.PacketConn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -59,6 +59,7 @@ func (s *UDPTun) ListenAndServe() {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			nm.Store(raddr.String(), pc)
 | 
								nm.Store(raddr.String(), pc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			go func() {
 | 
								go func() {
 | 
				
			||||||
				timedCopy(c, raddr, pc, 2*time.Minute)
 | 
									timedCopy(c, raddr, pc, 2*time.Minute)
 | 
				
			||||||
				pc.Close()
 | 
									pc.Close()
 | 
				
			||||||
 | 
				
			|||||||
@ -69,7 +69,12 @@ func (s *UoTTun) ListenAndServe() {
 | 
				
			|||||||
			c.WriteTo(resp, clientAddr)
 | 
								c.WriteTo(resp, clientAddr)
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rc.Write(buf[:n])
 | 
							_, err = rc.Write(buf[:n])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logf("proxy-uottun remote write error: %v", err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		logf("proxy-uottun %s <-> %s", clientAddr, s.raddr)
 | 
							logf("proxy-uottun %s <-> %s", clientAddr, s.raddr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user