mirror of
				https://github.com/nadoo/glider.git
				synced 2025-11-04 15:52:38 +08:00 
			
		
		
		
	udptun: use routine to handle upstream connection
This commit is contained in:
		
							parent
							
								
									3dc02c246b
								
							
						
					
					
						commit
						4b0388a47d
					
				@ -2,8 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[](https://travis-ci.org/nadoo/glider)
 | 
					[](https://travis-ci.org/nadoo/glider)
 | 
				
			||||||
[](https://goreportcard.com/report/github.com/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)
 | 
				
			||||||
[](https://github.com/nadoo/glider/releases)
 | 
					[](https://github.com/nadoo/glider/releases)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -61,7 +59,7 @@ TODO:
 | 
				
			|||||||
Binary: 
 | 
					Binary: 
 | 
				
			||||||
- [https://github.com/nadoo/glider/releases](https://github.com/nadoo/glider/releases)
 | 
					- [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
 | 
					```bash
 | 
				
			||||||
go get -u github.com/nadoo/glider
 | 
					go get -u github.com/nadoo/glider
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										86
									
								
								tproxy.go
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								tproxy.go
									
									
									
									
									
								
							@ -1,10 +1,18 @@
 | 
				
			|||||||
// +build linux
 | 
					// +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
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
 | 
						"unsafe"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TProxy struct
 | 
					// TProxy struct
 | 
				
			||||||
@ -42,13 +50,13 @@ func (s *TProxy) ListenAndServeUDP() {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	listener, err := net.ListenUDP("udp", laddr)
 | 
						lc, err := net.ListenUDP("udp", laddr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-tproxy failed to listen on %s: %v", s.addr, err)
 | 
							logf("proxy-tproxy failed to listen on %s: %v", s.addr, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fd, err := listener.File()
 | 
						fd, err := lc.File()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logf("proxy-tproxy failed to get file descriptor: %v", err)
 | 
							logf("proxy-tproxy failed to get file descriptor: %v", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@ -68,4 +76,78 @@ func (s *TProxy) ListenAndServeUDP() {
 | 
				
			|||||||
		return
 | 
							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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										32
									
								
								uottun.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								uottun.go
									
									
									
									
									
								
							@ -45,24 +45,26 @@ func (s *UoTTun) ListenAndServe() {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// NOTE: acturally udp over tcp
 | 
							go func() {
 | 
				
			||||||
		rc, err := s.sDialer.Dial("udp", s.raddr)
 | 
								// NOTE: acturally udp over tcp
 | 
				
			||||||
		if err != nil {
 | 
								rc, err := s.sDialer.Dial("udp", s.raddr)
 | 
				
			||||||
			logf("failed to connect to server %v: %v", s.raddr, err)
 | 
								if err != nil {
 | 
				
			||||||
			continue
 | 
									logf("failed to connect to server %v: %v", s.raddr, err)
 | 
				
			||||||
		}
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rc.Write(buf[:n])
 | 
								rc.Write(buf[:n])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		resp, err := ioutil.ReadAll(rc)
 | 
								resp, err := ioutil.ReadAll(rc)
 | 
				
			||||||
		if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
			logf("error in ioutil.ReadAll: %s\n", err)
 | 
									logf("error in ioutil.ReadAll: %s\n", err)
 | 
				
			||||||
			return
 | 
									return
 | 
				
			||||||
		}
 | 
								}
 | 
				
			||||||
		rc.Close()
 | 
								rc.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		c.WriteTo(resp, clientAddr)
 | 
								c.WriteTo(resp, clientAddr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		logf("proxy-uottun %s <-> %s", clientAddr, s.raddr)
 | 
								logf("proxy-uottun %s <-> %s", clientAddr, s.raddr)
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user