mirror of
				https://github.com/nadoo/glider.git
				synced 2025-10-30 13:25:52 +08:00 
			
		
		
		
	trojan: added udp support
This commit is contained in:
		
							parent
							
								
									2520a1c8b4
								
							
						
					
					
						commit
						bfcf9272dc
					
				
							
								
								
									
										79
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								README.md
									
									
									
									
									
								
							| @ -15,58 +15,26 @@ we can set up local listeners as proxy servers, and forward requests to internet | ||||
| ``` | ||||
| 
 | ||||
| ## Features | ||||
| 
 | ||||
| Listen (local proxy server): | ||||
| 
 | ||||
| - Socks5 proxy(tcp&udp) | ||||
| - Http proxy(tcp) | ||||
| - SS proxy(tcp&udp) | ||||
| - Linux transparent proxy(iptables redirect) | ||||
| - TCP tunnel | ||||
| - UDP tunnel | ||||
| - UDP over TCP tunnel | ||||
| - TLS, use it together with above proxy protocols(tcp) | ||||
| - Unix domain socket, use it together with above proxy protocols(tcp) | ||||
| - KCP protocol, use it together with above proxy protocols(tcp) | ||||
| 
 | ||||
| Forward (local proxy client/upstream proxy server): | ||||
| 
 | ||||
| - Socks5 proxy(tcp&udp) | ||||
| - Http proxy(tcp) | ||||
| - SS proxy(tcp&udp&uot) | ||||
| - SSR proxy(tcp) | ||||
| - VMess proxy(tcp) | ||||
| - Trojan proxy(tcp) | ||||
| - TLS, use it together with above proxy protocols(tcp) | ||||
| - Websocket, use it together with above proxy protocols(tcp) | ||||
| - Unix domain socket, use it together with above proxy protocols(tcp) | ||||
| - KCP protocol, use it together with above proxy protocols(tcp) | ||||
| - Simple-Obfs, use it together with above proxy protocols(tcp) | ||||
| 
 | ||||
| DNS Forwarding Server (udp2tcp): | ||||
| 
 | ||||
| - DNS Over Proxy | ||||
| - Listen on UDP and forward dns requests to remote dns server in TCP via forwarders | ||||
| - Specify different upstream dns server based on destinations(in rule file) | ||||
| - Tunnel mode: forward to a fixed upstream dns server | ||||
| - Add resolved IPs to proxy rules | ||||
| - Add resolved IPs to ipset | ||||
| - DNS cache | ||||
| - Custom dns record | ||||
| 
 | ||||
| IPSet Management (Linux kernel version >= 2.6.32): | ||||
| 
 | ||||
| - Add ip/cidrs from rule files on startup | ||||
| - Add resolved ips for domains from rule files by dns forwarding server | ||||
| 
 | ||||
| General: | ||||
| 
 | ||||
| - Proxy Server( -listen ) | ||||
| - Proxy Client( -forward ) | ||||
| - Http and socks5 on the same port | ||||
| - Forwarder chain | ||||
| - RR/HA/LHA/DH strategy for multiple forwarders | ||||
| - Periodical proxy checking | ||||
| - Rule proxy based on destinations: [Config Examples](config/examples) | ||||
| - Send requests from specific ip/interface | ||||
| - DNS Forwarding Server: | ||||
|   - DNS Over Proxy | ||||
|   - Listen on UDP and forward dns requests to remote dns server in TCP via forwarders | ||||
|   - Specify different upstream dns server based on destinations(in rule file) | ||||
|   - Tunnel mode: forward to a fixed upstream dns server | ||||
|   - Add resolved IPs to proxy rules | ||||
|   - Add resolved IPs to ipset | ||||
|   - DNS cache | ||||
|   - Custom dns record | ||||
| - IPSet Management (Linux kernel version >= 2.6.32): | ||||
|   - Add ip/cidrs from rule files on startup | ||||
|   - Add resolved ips for domains from rule files by dns forwarding server | ||||
| 
 | ||||
| TODO: | ||||
| 
 | ||||
| @ -76,6 +44,25 @@ TODO: | ||||
| - [ ] TUN/TAP device support | ||||
| - [ ] SSH tunnel support (maybe) | ||||
| 
 | ||||
| ### Protocols | ||||
| Protocol | Listen/TCP |  Listen/UDP | Forward/TCP | Forward/UDP | ||||
| -|-|-|-|- | ||||
| Socks5 | √ | √ | √ | √ | ||||
| Http | √ |  | √ |  | ||||
| SS | √ | √ | √ | √ | ||||
| Redir | √ |  | |  | ||||
| Tcptun | √ |  | |  | ||||
| Udptun |  | √ | |  | ||||
| UoTtun |  | √ | |  | ||||
| TLS | √ |  | √ |  | ||||
| Unix | √ |  | √ |  | ||||
| KCP |  | √ | √ |  | ||||
| SSR |  |  | √ |  | ||||
| VMess |  |  | √ |  | ||||
| Trojan |  |  | √ | √ | ||||
| WebSocket |  |  | √ |  | ||||
| Simple-Obfs |  |  | √ |  | ||||
| 
 | ||||
| ## Install | ||||
| 
 | ||||
| Binary: | ||||
|  | ||||
| @ -13,26 +13,22 @@ const ( | ||||
| 	AuthPassword = 2 | ||||
| ) | ||||
| 
 | ||||
| // SOCKS request commands as defined in RFC 1928 section 4.
 | ||||
| // SOCKS request commands as defined in RFC 1928 section 4
 | ||||
| const ( | ||||
| 	CmdConnect      = 1 | ||||
| 	CmdBind         = 2 | ||||
| 	CmdUDPAssociate = 3 | ||||
| 	CmdConnect      byte = 1 | ||||
| 	CmdBind         byte = 2 | ||||
| 	CmdUDPAssociate byte = 3 | ||||
| ) | ||||
| 
 | ||||
| // SOCKS address types as defined in RFC 1928 section 5.
 | ||||
| // SOCKS address types as defined in RFC 1928 section 5
 | ||||
| const ( | ||||
| 	ATypIP4    = 1 | ||||
| 	ATypDomain = 3 | ||||
| 	ATypIP6    = 4 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// maximum size of SOCKS address in bytes.
 | ||||
| 	MaxAddrLen = 1 + 1 + 255 + 2 | ||||
| 	// minimum size of SOCKS address in bytes.
 | ||||
| 	MinAddrLen = 5 | ||||
| ) | ||||
| // MaxAddrLen is the maximum size of SOCKS address in bytes
 | ||||
| const MaxAddrLen = 1 + 1 + 255 + 2 | ||||
| 
 | ||||
| // Errors are socks5 errors
 | ||||
| var Errors = []error{ | ||||
|  | ||||
| @ -58,7 +58,7 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { | ||||
| 		return n, raddr, err | ||||
| 	} | ||||
| 
 | ||||
| 	if n < socks.MinAddrLen { | ||||
| 	if n < 3 { | ||||
| 		return n, raddr, errors.New("not enough size to get addr") | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -39,10 +39,6 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { | ||||
| 		return n, raddr, err | ||||
| 	} | ||||
| 
 | ||||
| 	if n < socks.MinAddrLen { | ||||
| 		return n, raddr, errors.New("not enough size to get addr") | ||||
| 	} | ||||
| 
 | ||||
| 	tgtAddr := socks.SplitAddr(buf) | ||||
| 	if tgtAddr == nil { | ||||
| 		return n, raddr, errors.New("can not get addr") | ||||
|  | ||||
							
								
								
									
										75
									
								
								proxy/trojan/packet.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								proxy/trojan/packet.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| // https://trojan-gfw.github.io/trojan/protocol
 | ||||
| // If the connection is a UDP ASSOCIATE, then each UDP packet has the following format:
 | ||||
| // +------+----------+----------+--------+---------+----------+
 | ||||
| // | ATYP | DST.ADDR | DST.PORT | Length |  CRLF   | Payload  |
 | ||||
| // +------+----------+----------+--------+---------+----------+
 | ||||
| // |  1   | Variable |    2     |   2    | X'0D0A' | Variable |
 | ||||
| // +------+----------+----------+--------+---------+----------+
 | ||||
| package trojan | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 
 | ||||
| 	"github.com/nadoo/glider/common/conn" | ||||
| 	"github.com/nadoo/glider/common/socks" | ||||
| ) | ||||
| 
 | ||||
| // PktConn .
 | ||||
| type PktConn struct { | ||||
| 	net.Conn | ||||
| 
 | ||||
| 	tgtAddr socks.Addr | ||||
| } | ||||
| 
 | ||||
| func NewPktConn(c net.Conn, tgtAddr socks.Addr) *PktConn { | ||||
| 	pc := &PktConn{ | ||||
| 		Conn:    c, | ||||
| 		tgtAddr: tgtAddr, | ||||
| 	} | ||||
| 	return pc | ||||
| } | ||||
| 
 | ||||
| func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) { | ||||
| 	// ATYP, DST.ADDR, DST.PORT
 | ||||
| 	_, err := socks.ReadAddr(pc.Conn) | ||||
| 	if err != nil { | ||||
| 		return 0, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Length
 | ||||
| 	if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil { | ||||
| 		return 0, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	length := int(binary.BigEndian.Uint16(b[:2])) | ||||
| 	if length > conn.UDPBufSize { | ||||
| 		return 0, nil, errors.New("packet invalid") | ||||
| 	} | ||||
| 
 | ||||
| 	// CRLF
 | ||||
| 	if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil { | ||||
| 		return 0, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Payload
 | ||||
| 	n, err := io.ReadFull(pc.Conn, b[:length]) | ||||
| 	if err != nil { | ||||
| 		return 0, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO: check the addr in return value, it's a fake packetConn so the addr is not valid
 | ||||
| 	return n, nil, err | ||||
| } | ||||
| 
 | ||||
| func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	buf.Write(pc.tgtAddr) | ||||
| 	binary.Write(&buf, binary.BigEndian, uint16(len(b))) | ||||
| 	buf.WriteString("\r\n") | ||||
| 	buf.Write(b) | ||||
| 	return pc.Write(buf.Bytes()) | ||||
| } | ||||
| @ -32,7 +32,6 @@ import ( | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/tls" | ||||
| 	"encoding/hex" | ||||
| 	"errors" | ||||
| 	"net" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| @ -42,7 +41,7 @@ import ( | ||||
| 	"github.com/nadoo/glider/proxy" | ||||
| ) | ||||
| 
 | ||||
| // Trojan is a base trojan struct.
 | ||||
| // Trojan is a base trojan struct
 | ||||
| type Trojan struct { | ||||
| 	dialer     proxy.Dialer | ||||
| 	proxy      proxy.Proxy | ||||
| @ -115,8 +114,13 @@ func (s *Trojan) Addr() string { | ||||
| 
 | ||||
| // Dial connects to the address addr on the network net via the proxy.
 | ||||
| func (s *Trojan) Dial(network, addr string) (net.Conn, error) { | ||||
| 	return s.dial(network, addr) | ||||
| } | ||||
| 
 | ||||
| func (s *Trojan) dial(network, addr string) (net.Conn, error) { | ||||
| 	rc, err := s.dialer.Dial("tcp", s.addr) | ||||
| 	if err != nil { | ||||
| 		log.F("[trojan]: dial to %s error: %s", s.addr, err) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| @ -128,14 +132,28 @@ func (s *Trojan) Dial(network, addr string) (net.Conn, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	buf.Write(s.pass[:]) | ||||
| 	buf.WriteString("\r\n") | ||||
| 	buf.WriteByte(socks.CmdConnect) | ||||
| 
 | ||||
| 	cmd := socks.CmdConnect | ||||
| 	if network == "udp" { | ||||
| 		cmd = socks.CmdUDPAssociate | ||||
| 	} | ||||
| 	buf.WriteByte(cmd) | ||||
| 
 | ||||
| 	buf.Write(socks.ParseAddr(addr)) | ||||
| 	buf.WriteString("\r\n") | ||||
| 	_, err = tlsConn.Write(buf.Bytes()) | ||||
| 
 | ||||
| 	return tlsConn, err | ||||
| } | ||||
| 
 | ||||
| // DialUDP connects to the given address via the proxy.
 | ||||
| func (s *Trojan) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { | ||||
| 	return nil, nil, errors.New("trojan client does not support udp now") | ||||
| 	c, err := s.dial("udp", addr) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	pkc := NewPktConn(c, socks.ParseAddr(addr)) | ||||
| 
 | ||||
| 	return pkc, nil, nil | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 nadoo
						nadoo