mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +08:00
tproxy: add base udp tproxy listener codes
This commit is contained in:
parent
4fe5eb97bb
commit
fdbb9a5034
@ -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