mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 15:52:38 +08:00 
			
		
		
		
	tproxy: add base udp tproxy listener codes
This commit is contained in:
		
							parent
							
								
									c8e63f2dc2
								
							
						
					
					
						commit
						997c495730
					
				@ -42,7 +42,7 @@ General:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TODO:
 | 
					TODO:
 | 
				
			||||||
- [x] UDP over TCP Tunnel (client <-udp-> uottun <-tcp-> ss <-udp-> target)
 | 
					- [x] UDP over TCP Tunnel (client <-udp-> uottun <-tcp-> ss <-udp-> target)
 | 
				
			||||||
- [ ] Linux tproxy support
 | 
					- [ ] Transparent UDP proxy (linux tproxy)
 | 
				
			||||||
- [ ] TUN/TAP device support
 | 
					- [ ] TUN/TAP device support
 | 
				
			||||||
- [ ] Code refactoring: support proxy registering so it can be pluggable
 | 
					- [ ] Code refactoring: support proxy registering so it can be pluggable
 | 
				
			||||||
- [ ] Conditional compilation so we can abandon needless proxy type and get a smaller binary size
 | 
					- [ ] Conditional compilation so we can abandon needless proxy type and get a smaller binary size
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,7 @@ dns://53
 | 
				
			|||||||
# global remote dns server (you can specify different dns server in rule file)
 | 
					# global remote dns server (you can specify different dns server in rule file)
 | 
				
			||||||
dnsserver=8.8.8.8:53
 | 
					dnsserver=8.8.8.8:53
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Create and mange ipset on linux based on destinations in rule files
 | 
					# Create and manage ipset on linux based on destinations in rule files
 | 
				
			||||||
#   - add ip/cidrs in rule files on startup
 | 
					#   - add ip/cidrs in rule files on startup
 | 
				
			||||||
#   - add resolved ips for domains in rule files by dns forwarder server 
 | 
					#   - add resolved ips for domains in rule files by dns forwarder server 
 | 
				
			||||||
# Usually used in transparent proxy mode on linux
 | 
					# Usually used in transparent proxy mode on linux
 | 
				
			||||||
 | 
				
			|||||||
@ -8,8 +8,6 @@ import (
 | 
				
			|||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/shadowsocks/go-shadowsocks2/socks"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@ -32,7 +30,7 @@ func NewRedirProxy(addr string, sDialer Dialer) (*RedirProxy, error) {
 | 
				
			|||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServe redirected requests as a server.
 | 
					// ListenAndServe .
 | 
				
			||||||
func (s *RedirProxy) ListenAndServe() {
 | 
					func (s *RedirProxy) ListenAndServe() {
 | 
				
			||||||
	l, err := net.Listen("tcp", s.addr)
 | 
						l, err := net.Listen("tcp", s.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -84,7 +82,7 @@ func (s *RedirProxy) ListenAndServe() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get the original destination of a TCP connection.
 | 
					// Get the original destination of a TCP connection.
 | 
				
			||||||
func getOrigDst(conn net.Conn, ipv6 bool) (socks.Addr, error) {
 | 
					func getOrigDst(conn net.Conn, ipv6 bool) (Addr, error) {
 | 
				
			||||||
	c, ok := conn.(*net.TCPConn)
 | 
						c, ok := conn.(*net.TCPConn)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return nil, errors.New("only work with TCP connection")
 | 
							return nil, errors.New("only work with TCP connection")
 | 
				
			||||||
@ -112,7 +110,7 @@ func getOrigDst(conn net.Conn, ipv6 bool) (socks.Addr, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
 | 
					// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
 | 
				
			||||||
func getorigdst(fd uintptr) (socks.Addr, error) {
 | 
					func getorigdst(fd uintptr) (Addr, error) {
 | 
				
			||||||
	raw := syscall.RawSockaddrInet4{}
 | 
						raw := syscall.RawSockaddrInet4{}
 | 
				
			||||||
	siz := unsafe.Sizeof(raw)
 | 
						siz := unsafe.Sizeof(raw)
 | 
				
			||||||
	if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
 | 
						if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
 | 
				
			||||||
@ -120,7 +118,7 @@ func getorigdst(fd uintptr) (socks.Addr, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addr := make([]byte, 1+net.IPv4len+2)
 | 
						addr := make([]byte, 1+net.IPv4len+2)
 | 
				
			||||||
	addr[0] = socks.AtypIPv4
 | 
						addr[0] = socks5IP4
 | 
				
			||||||
	copy(addr[1:1+net.IPv4len], raw.Addr[:])
 | 
						copy(addr[1:1+net.IPv4len], raw.Addr[:])
 | 
				
			||||||
	port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian
 | 
						port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian
 | 
				
			||||||
	addr[1+net.IPv4len], addr[1+net.IPv4len+1] = port[0], port[1]
 | 
						addr[1+net.IPv4len], addr[1+net.IPv4len+1] = port[0], port[1]
 | 
				
			||||||
@ -129,7 +127,7 @@ func getorigdst(fd uintptr) (socks.Addr, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Call ipv6_getorigdst() from linux/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
 | 
					// Call ipv6_getorigdst() from linux/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
 | 
				
			||||||
// NOTE: I haven't tried yet but it should work since Linux 3.8.
 | 
					// NOTE: I haven't tried yet but it should work since Linux 3.8.
 | 
				
			||||||
func ipv6_getorigdst(fd uintptr) (socks.Addr, error) {
 | 
					func ipv6_getorigdst(fd uintptr) (Addr, error) {
 | 
				
			||||||
	raw := syscall.RawSockaddrInet6{}
 | 
						raw := syscall.RawSockaddrInet6{}
 | 
				
			||||||
	siz := unsafe.Sizeof(raw)
 | 
						siz := unsafe.Sizeof(raw)
 | 
				
			||||||
	if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
 | 
						if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
 | 
				
			||||||
@ -137,7 +135,7 @@ func ipv6_getorigdst(fd uintptr) (socks.Addr, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addr := make([]byte, 1+net.IPv6len+2)
 | 
						addr := make([]byte, 1+net.IPv6len+2)
 | 
				
			||||||
	addr[0] = socks.AtypIPv6
 | 
						addr[0] = socks5IP6
 | 
				
			||||||
	copy(addr[1:1+net.IPv6len], raw.Addr[:])
 | 
						copy(addr[1:1+net.IPv6len], raw.Addr[:])
 | 
				
			||||||
	port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian
 | 
						port := (*[2]byte)(unsafe.Pointer(&raw.Port)) // big-endian
 | 
				
			||||||
	addr[1+net.IPv6len], addr[1+net.IPv6len+1] = port[0], port[1]
 | 
						addr[1+net.IPv6len], addr[1+net.IPv6len+1] = port[0], port[1]
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ func NewRedirProxy(addr string, sDialer Dialer) (*RedirProxy, error) {
 | 
				
			|||||||
	return nil, errors.New("redir not supported on this os")
 | 
						return nil, errors.New("redir not supported on this os")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServe redirected requests as a server.
 | 
					// ListenAndServe .
 | 
				
			||||||
func (s *RedirProxy) ListenAndServe() {
 | 
					func (s *RedirProxy) ListenAndServe() {
 | 
				
			||||||
	log.Fatal("redir not supported on this os")
 | 
						log.Fatal("redir not supported on this os")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,7 @@ func NewSOCKS5(addr, user, pass string, cDialer Dialer, sDialer Dialer) (*SOCKS5
 | 
				
			|||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServe connects to the address addr on the network net via the SOCKS5 proxy.
 | 
					// ListenAndServe .
 | 
				
			||||||
func (s *SOCKS5) ListenAndServe() {
 | 
					func (s *SOCKS5) ListenAndServe() {
 | 
				
			||||||
	l, err := net.Listen("tcp", s.addr)
 | 
						l, err := net.Listen("tcp", s.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ func NewTCPTun(addr, raddr string, sDialer Dialer) (*TCPTun, error) {
 | 
				
			|||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServe redirected requests as a server.
 | 
					// ListenAndServe .
 | 
				
			||||||
func (s *TCPTun) ListenAndServe() {
 | 
					func (s *TCPTun) ListenAndServe() {
 | 
				
			||||||
	l, err := net.Listen("tcp", s.addr)
 | 
						l, err := net.Listen("tcp", s.addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										68
									
								
								tproxy.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								tproxy.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TProxy struct {
 | 
				
			||||||
 | 
						*Forwarder        // as client
 | 
				
			||||||
 | 
						sDialer    Dialer // dialer for server
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewTProxy returns a tproxy.
 | 
				
			||||||
 | 
					func NewTProxy(addr string, sDialer Dialer) (*TProxy, error) {
 | 
				
			||||||
 | 
						s := &TProxy{
 | 
				
			||||||
 | 
							Forwarder: NewForwarder(addr, nil),
 | 
				
			||||||
 | 
							sDialer:   sDialer,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return s, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServe .
 | 
				
			||||||
 | 
					func (s *TProxy) ListenAndServe() {
 | 
				
			||||||
 | 
						// go s.ListenAndServeTCP()
 | 
				
			||||||
 | 
						s.ListenAndServeUDP()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *TProxy) ListenAndServeTCP() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *TProxy) ListenAndServeUDP() {
 | 
				
			||||||
 | 
						laddr, err := net.ResolveUDPAddr("udp", s.addr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logf("proxy-tproxy failed to resolve addr %s: %v", s.addr, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						listener, err := net.ListenUDP("udp", laddr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logf("proxy-tproxy failed to listen on %s: %v", s.addr, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fd, err := listener.File()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logf("proxy-tproxy failed to get file descriptor: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer fd.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fileDescriptor := int(fd.Fd())
 | 
				
			||||||
 | 
						if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
 | 
				
			||||||
 | 
							syscall.Close(fileDescriptor)
 | 
				
			||||||
 | 
							logf("proxy-tproxy failed to set socket option IP_TRANSPARENT: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1); err != nil {
 | 
				
			||||||
 | 
							syscall.Close(fileDescriptor)
 | 
				
			||||||
 | 
							logf("proxy-tproxy failed to set socket option IP_RECVORIGDSTADDR: %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								tproxy_other.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tproxy_other.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					// +build !linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TProxy struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewTProxy returns a tproxy.
 | 
				
			||||||
 | 
					func NewTProxy(addr string, sDialer Dialer) (*TProxy, error) {
 | 
				
			||||||
 | 
						return nil, errors.New("tproxy not supported on this os")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListenAndServe .
 | 
				
			||||||
 | 
					func (s *TProxy) ListenAndServe() {
 | 
				
			||||||
 | 
						log.Fatal("tproxy not supported on this os")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -24,7 +24,7 @@ func NewUoTTun(addr, raddr string, sDialer Dialer) (*UoTTun, error) {
 | 
				
			|||||||
	return s, nil
 | 
						return s, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListenAndServe redirected requests as a server.
 | 
					// ListenAndServe .
 | 
				
			||||||
func (s *UoTTun) ListenAndServe() {
 | 
					func (s *UoTTun) ListenAndServe() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c, err := net.ListenPacket("udp", s.addr)
 | 
						c, err := net.ListenPacket("udp", s.addr)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user