mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +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
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,12 @@ func (s *UoTTun) ListenAndServe() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
// NOTE: acturally udp over tcp
|
// NOTE: acturally udp over tcp
|
||||||
rc, err := s.sDialer.Dial("udp", s.raddr)
|
rc, err := s.sDialer.Dial("udp", s.raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("failed to connect to server %v: %v", s.raddr, err)
|
logf("failed to connect to server %v: %v", s.raddr, err)
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rc.Write(buf[:n])
|
rc.Write(buf[:n])
|
||||||
@ -64,5 +65,6 @@ func (s *UoTTun) ListenAndServe() {
|
|||||||
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