mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 07:42:38 +08:00 
			
		
		
		
	udptun: use routine to handle upstream connection
This commit is contained in:
		
							parent
							
								
									21f9ab3bbe
								
							
						
					
					
						commit
						c293e58ac5
					
				@ -2,8 +2,6 @@
 | 
			
		||||
 | 
			
		||||
[](https://travis-ci.org/nadoo/glider)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/nadoo/glider)
 | 
			
		||||
[](https://golang.org/dl/)
 | 
			
		||||
[](https://github.com/nadoo/glider/blob/master/LICENSE)
 | 
			
		||||
[](https://github.com/nadoo/glider/releases)
 | 
			
		||||
[](https://github.com/nadoo/glider/releases)
 | 
			
		||||
 | 
			
		||||
@ -61,7 +59,7 @@ TODO:
 | 
			
		||||
Binary: 
 | 
			
		||||
- [https://github.com/nadoo/glider/releases](https://github.com/nadoo/glider/releases)
 | 
			
		||||
 | 
			
		||||
Go Get (requires **Go 1.9 or newer**):
 | 
			
		||||
Go Get (requires **Go 1.9+** ):
 | 
			
		||||
```bash
 | 
			
		||||
go get -u github.com/nadoo/glider
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										86
									
								
								tproxy.go
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								tproxy.go
									
									
									
									
									
								
							@ -1,10 +1,18 @@
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
// ref: https://www.kernel.org/doc/Documentation/networking/tproxy.txt
 | 
			
		||||
// @LiamHaworth: https://github.com/LiamHaworth/go-tproxy/blob/master/tproxy_udp.go
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TProxy struct
 | 
			
		||||
@ -42,13 +50,13 @@ func (s *TProxy) ListenAndServeUDP() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	listener, err := net.ListenUDP("udp", laddr)
 | 
			
		||||
	lc, 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()
 | 
			
		||||
	fd, err := lc.File()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logf("proxy-tproxy failed to get file descriptor: %v", err)
 | 
			
		||||
		return
 | 
			
		||||
@ -68,4 +76,78 @@ func (s *TProxy) ListenAndServeUDP() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
 | 
			
		||||
		buf := make([]byte, 1024)
 | 
			
		||||
		_, srcAddr, dstAddr, err := ReadFromUDP(lc, buf)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
 | 
			
		||||
				logf("proxy-tproxy Temporary error while reading data: %s", netErr)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			logf("proxy-tproxy Unrecoverable error while reading data: %s", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		logf("proxy-tproxy Accepting UDP connection from %s with destination of %s", srcAddr.String(), dstAddr.String())
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadFromUDP reads a UDP packet from c, copying the payload into b.
 | 
			
		||||
// It returns the number of bytes copied into b and the return address
 | 
			
		||||
// that was on the packet.
 | 
			
		||||
//
 | 
			
		||||
// Out-of-band data is also read in so that the original destination
 | 
			
		||||
// address can be identified and parsed.
 | 
			
		||||
func ReadFromUDP(conn *net.UDPConn, b []byte) (int, *net.UDPAddr, *net.UDPAddr, error) {
 | 
			
		||||
	oob := make([]byte, 1024)
 | 
			
		||||
	n, oobn, _, addr, err := conn.ReadMsgUDP(b, oob)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	msgs, err := syscall.ParseSocketControlMessage(oob[:oobn])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, nil, nil, fmt.Errorf("parsing socket control message: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var originalDst *net.UDPAddr
 | 
			
		||||
	for _, msg := range msgs {
 | 
			
		||||
		if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR {
 | 
			
		||||
			originalDstRaw := &syscall.RawSockaddrInet4{}
 | 
			
		||||
			if err = binary.Read(bytes.NewReader(msg.Data), binary.LittleEndian, originalDstRaw); err != nil {
 | 
			
		||||
				return 0, nil, nil, fmt.Errorf("reading original destination address: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			switch originalDstRaw.Family {
 | 
			
		||||
			case syscall.AF_INET:
 | 
			
		||||
				pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(originalDstRaw))
 | 
			
		||||
				p := (*[2]byte)(unsafe.Pointer(&pp.Port))
 | 
			
		||||
				originalDst = &net.UDPAddr{
 | 
			
		||||
					IP:   net.IPv4(pp.Addr[0], pp.Addr[1], pp.Addr[2], pp.Addr[3]),
 | 
			
		||||
					Port: int(p[0])<<8 + int(p[1]),
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			case syscall.AF_INET6:
 | 
			
		||||
				pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(originalDstRaw))
 | 
			
		||||
				p := (*[2]byte)(unsafe.Pointer(&pp.Port))
 | 
			
		||||
				originalDst = &net.UDPAddr{
 | 
			
		||||
					IP:   net.IP(pp.Addr[:]),
 | 
			
		||||
					Port: int(p[0])<<8 + int(p[1]),
 | 
			
		||||
					Zone: strconv.Itoa(int(pp.Scope_id)),
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
				return 0, nil, nil, fmt.Errorf("original destination is an unsupported network family")
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if originalDst == nil {
 | 
			
		||||
		return 0, nil, nil, fmt.Errorf("unable to obtain original destination: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return n, addr, originalDst, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -45,11 +45,12 @@ func (s *UoTTun) ListenAndServe() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		go func() {
 | 
			
		||||
			// NOTE: acturally udp over tcp
 | 
			
		||||
			rc, err := s.sDialer.Dial("udp", s.raddr)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logf("failed to connect to server %v: %v", s.raddr, err)
 | 
			
		||||
			continue
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			rc.Write(buf[:n])
 | 
			
		||||
@ -64,5 +65,6 @@ func (s *UoTTun) ListenAndServe() {
 | 
			
		||||
			c.WriteTo(resp, clientAddr)
 | 
			
		||||
 | 
			
		||||
			logf("proxy-uottun %s <-> %s", clientAddr, s.raddr)
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user