mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
tproxy: setsockopt in listener to suuport ipv6
This commit is contained in:
parent
792b244c59
commit
b0b043a280
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@ -11,7 +11,7 @@ on:
|
||||
env:
|
||||
DOCKERHUB_REPO: nadoo/glider
|
||||
GHCR_REPO: ghcr.io/nadoo/glider
|
||||
PLATFORMS: linux/amd64,linux/arm64,linux/arm/v7
|
||||
PLATFORMS: linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
|
@ -1,14 +1,11 @@
|
||||
package tproxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@ -35,8 +32,16 @@ func ListenUDP(network string, laddr *net.UDPAddr) (*net.UDPConn, error) {
|
||||
return nil, &net.OpError{Op: "listen", Net: network, Source: nil, Addr: laddr, Err: fmt.Errorf("set socket option: IP_TRANSPARENT: %s", err)}
|
||||
}
|
||||
|
||||
if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1); err != nil {
|
||||
return nil, &net.OpError{Op: "listen", Net: network, Source: nil, Addr: laddr, Err: fmt.Errorf("set socket option: IP_RECVORIGDSTADDR: %s", err)}
|
||||
if laddr.IP == nil || laddr.IP.To4() != nil {
|
||||
if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1); err != nil {
|
||||
return nil, &net.OpError{Op: "listen", Net: network, Source: nil, Addr: laddr, Err: fmt.Errorf("set socket option: IP_RECVORIGDSTADDR: %s", err)}
|
||||
}
|
||||
}
|
||||
|
||||
if laddr.IP == nil || laddr.IP.To4() == nil {
|
||||
if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1); err != nil {
|
||||
return nil, &net.OpError{Op: "listen", Net: network, Source: nil, Addr: laddr, Err: fmt.Errorf("set socket option: IPV6_RECVORIGDSTADDR: %s", err)}
|
||||
}
|
||||
}
|
||||
|
||||
return listener, nil
|
||||
@ -60,44 +65,20 @@ func ReadFromUDP(conn *net.UDPConn, b []byte) (int, *net.UDPAddr, *net.UDPAddr,
|
||||
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.Level == syscall.SOL_IPV6) &&
|
||||
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 msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR {
|
||||
ip := net.IP(msg.Data[4:8])
|
||||
port := binary.BigEndian.Uint16(msg.Data[2:4])
|
||||
return n, addr, &net.UDPAddr{IP: ip, Port: int(port)}, nil
|
||||
}
|
||||
if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == unix.IPV6_RECVORIGDSTADDR {
|
||||
ip := net.IP(msg.Data[8:24])
|
||||
port := binary.BigEndian.Uint16(msg.Data[2:4])
|
||||
return n, addr, &net.UDPAddr{IP: ip, Port: int(port)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if originalDst == nil {
|
||||
return 0, nil, nil, fmt.Errorf("unable to obtain original destination: %s", err)
|
||||
}
|
||||
|
||||
return n, addr, originalDst, nil
|
||||
return 0, nil, nil, fmt.Errorf("unable to obtain original destination: %s", err)
|
||||
}
|
||||
|
||||
// ListenPacket acts like net.ListenPacket but the addr could be non-local.
|
||||
|
Loading…
Reference in New Issue
Block a user