go-gost / gost

GO Simple Tunnel - a simple tunnel written in golang
https://gost.run
MIT License
3.72k stars 469 forks source link

[Feature Request] Linux Network Namespace (netns) support #493

Open przemyslaw0 opened 1 month ago

przemyslaw0 commented 1 month ago

GOST would listen in a specified netns and connect to another.

From here: https://github.com/3proxy/3proxy/issues/486

Please consider implement proxying between network namespaces. Despite broad 
info that process can only have sockets in one network namespace actually it can 
have opened sockets in multiple namespaces. All the opened sockets aren't affected 
by a setns system call. A socket is a network device with associated network namespace 
and new accepted connections are also belongs to the original socket namespace.

So the procedure is:

    Create a listen proxy socket

    Call setns() function and move the process into a new namespace

    Do chroot and other privilege deescalation stuff

    Do the main proxy loop as usual, accept connections on original socket 
and make new connections in the new network namespace

I don't know how to arrange this with a complex configs of multiple proxy 
interfaces but it is possible to make a simple proxy between namespaces 
this way without the performance overhead and setup pain associated with 
virtual veth interfaces between namespaces.

A prototype of this feature is implemented here (in Rust): https://github.com/vi/netns_tcp_bridge/blob/main/src/main.rs

This Go package is useful for this implementation: https://github.com/vishvananda/netns

ginuerzh commented 2 weeks ago

You can set network namespace for service and hop now.

case 1: listener in namespace ns1, but dialer in original namespace

gost -L :8080?netns=ns1

case 2: listener and dialer both in namespace ns1

gost -L ":8080?netns=ns1&netns.out=ns1"

case 3: listener in namespace ns1, hop node dialer in original namespace

gost -L :8080?netns=ns1 -F :1080

case 4: listener in namespace ns1, hop node dialer in namespace ns2

gost -L :8080?netns=ns1 -F :1080?netns=ns2
przemyslaw0 commented 2 weeks ago

I tested this implementation, there is a problem with UDP (at least in SOCKS5 listener/connector):

# ./gost -L "socks5://127.0.0.1:1111?udp=true&netns=nsx" -F "direct://:0?netns=blah"
{"handler":"socks5","kind":"service","level":"info","listener":"tcp","msg":"listening on 127.0.0.1:1111/tcp","service":"service-0","time":"2024-06-21T12:55:38.229-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:51363 <> 127.0.0.1:1111","remote":"127.0.0.1:51363","service":"service-0","time":"2024-06-21T12:55:51.406-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:40737 <> 127.0.0.1:1111","remote":"127.0.0.1:40737","service":"service-0","time":"2024-06-21T12:55:51.406-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:33295 <> 127.0.0.1:1111","remote":"127.0.0.1:33295","service":"service-0","time":"2024-06-21T12:55:51.406-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:49115 <> 127.0.0.1:1111","remote":"127.0.0.1:49115","service":"service-0","time":"2024-06-21T12:55:51.406-04:00"}
{"duration":722337,"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:40737 >< 127.0.0.1:1111","remote":"127.0.0.1:40737","service":"service-0","time":"2024-06-21T12:55:51.407-04:00"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0xdba1da]

goroutine 22 [running]:
github.com/go-gost/x/connector/direct.(*directConnector).Connect(0xc000594760, {0x168b258, 0xc000562270}, {0xc00007f680?, 0xc0005a3cd0?}, {0x1483e07, 0x3}, {0x0, 0x0}, {0xc000280058, ...})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/x@v0.0.0-20240621153818-2ae04628222a/connector/direct/connector.go:48 +0xfa
github.com/go-gost/core/chain.(*Transport).Connect(0xc0001a6a10, {0x168b258, 0xc000562270}, {0x1697800, 0x26374a0}, {0x1483e07, 0x3}, {0x0, 0x0})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/core@v0.0.0-20240621153412-5aede9a2b32f/chain/transport.go:125 +0x1a6
github.com/go-gost/x/chain.(*route).Dial(0xc000563050, {0x168b258, 0xc000562270}, {0x1483e07, 0x3}, {0x0, 0x0}, {0xc0005630e0, 0x5, 0x5})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/x@v0.0.0-20240621153818-2ae04628222a/chain/route.go:66 +0x1eb
github.com/go-gost/core/chain.(*Router).dial(0xc000196cf0, {0x168b258, 0xc000562270}, {0x1483e07, 0x3}, {0x0, 0x0})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/core@v0.0.0-20240621153412-5aede9a2b32f/chain/router.go:189 +0x871
github.com/go-gost/core/chain.(*Router).Dial(0xc000196cf0, {0x168b258, 0xc000562270}, {0x1483e07, 0x3}, {0x0, 0x0})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/core@v0.0.0-20240621153412-5aede9a2b32f/chain/router.go:126 +0xfc
github.com/go-gost/x/handler/socks/v5.(*socks5Handler).handleUDP(0xc000228000, {0x168b258, 0xc000562270}, {0x1697598, 0xc0004d3080}, {0x16a0dd0, 0xc00006e2b0})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/x@v0.0.0-20240621153818-2ae04628222a/handler/socks/v5/udp.go:59 +0x876
github.com/go-gost/x/handler/socks/v5.(*socks5Handler).Handle(0xc000228000, {0x168b258, 0xc000562270}, {0x1697598, 0xc0004d3080}, {0x0?, 0xc00006d718?, 0x409ade?})
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/x@v0.0.0-20240621153818-2ae04628222a/handler/socks/v5/handler.go:126 +0x9f1
github.com/go-gost/x/service.(*defaultService).Serve.func1()
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/x@v0.0.0-20240621153818-2ae04628222a/service/service.go:240 +0x503
created by github.com/go-gost/x/service.(*defaultService).Serve in goroutine 49
    /dev/shm/gost/gost/cmd/gost/go/pkg/mod/github.com/go-gost/x@v0.0.0-20240621153818-2ae04628222a/service/service.go:217 +0x967
ginuerzh commented 1 week ago

This issue should be fixed in commit https://github.com/go-gost/x/commit/f9bfca76ed1f5a4ce9908ec1b4f9fb226d80d870.

przemyslaw0 commented 1 week ago

I tested this new commit, now it works with netns=, but you also tried to solve the UDP associate problem, UDP associate has the same problem even with this commit:

/dev/shm/gost/gost/cmd/gost/gost -L "socks5://127.0.0.1:1085?udp=true" -F "socks5://127.0.0.1:1081?relay=udp"


$ dig @1.1.1.1
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out

; <<>> DiG 9.19.25-185-g392e7199df2-1-Debian <<>> @1.1.1.1
; (1 server found)
;; global options: +cmd
;; no servers could be reached

v2ray log:

2024/06/24 19:59:24 tcp:127.0.0.1:50084 rejected  proxy/socks: failed to read address > common/protocol: invalid domain name: 
2024/06/24 19:59:29 tcp:127.0.0.1:44910 rejected  proxy/socks: failed to read address > common/protocol: invalid domain name: 
2024/06/24 19:59:34 tcp:127.0.0.1:44914 rejected  proxy/socks: failed to read address > common/protocol: invalid domain name: 
2024/06/24 19:59:40 tcp:127.0.0.1:48420 rejected  proxy/socks: failed to read address > common/protocol: invalid domain name: 
2024/06/24 19:59:45 tcp:127.0.0.1:48434 rejected  proxy/socks: failed to read address > common/protocol: invalid domain name: 
2024/06/24 19:59:50 tcp:127.0.0.1:53620 rejected  proxy/socks: failed to read address > common/protocol: invalid domain name: 

3proxy log:

$ socks -l -p1084
240624234126.402 1084 00000 - 0.0.0.0:1084 0.0.0.0:0 0 0 0 Accepting connections [207611/2089621312]
240624235036.922 1084 00100 - 127.0.0.1:44818 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0
240624235041.923 1084 00100 - 127.0.0.1:50124 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0
240624235046.925 1084 00100 - 127.0.0.1:50128 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0

I tested socks5:// with udp=true and redu://.

ginuerzh commented 1 week ago

I used iperf3 and 3proxy (listening on :1080) to test the standard UDP relay function of SOCKS5, and it worked fine.

iperf3 -s
gost -L "socks://:11080?udp=true&notls=true&udpBufferSize=65535" -F "socks://:1080?relay=udp&udpBufferSize=65535"
gost -L tcp://:15201/:5201 -L "udp://:15201/:5201?keepalive=true&readBufferSize=65535" -F "socks5://:11080?relay=udp&udpBufferSize=65535"

then

iperf3 -c 127.0.0.1 -p 15201 -u
przemyslaw0 commented 1 week ago

@ginuerzh

I forgot to say, I tested with a transparent proxy pointing to SOCKS5@GOST and GOST pointing to another SOCKS5 server (3proxy).

You can reproduce the problem with this (network namespaces):

ip netns add ns1
ip link add veth1 type veth peer name peer1 netns ns1
ip link set veth1 up
ip addr add 10.0.11.1/24 dev veth1
ip netns exec ns1 ip link set peer1 up
ip netns exec ns1 ip link set lo up
ip netns exec ns1 ip addr add 10.0.11.2/24 dev peer1
ip netns exec ns1 ip li set lo up

ip netns add ns2
ip netns exec ns1 ip li add veth2 type veth peer name peer2 netns ns2
ip netns exec ns1 ip li set veth2 up
ip netns exec ns1 ip addr add 10.0.22.1/24 dev veth2
ip netns exec ns2 ip li set peer2 up
ip netns exec ns2 ip addr add 10.0.22.2/24 dev peer2
ip netns exec ns2 ip route add default via 10.0.22.1 dev peer2

ip netns exec ns1 ip -4 route add local default dev veth2 table 1112
ip netns exec ns1 ip -4 rule add fwmark 1112 table 1112
ip netns exec ns1 iptables -t mangle -N DIVERT
ip netns exec ns1 iptables -t mangle -A PREROUTING -p udp -m socket -j DIVERT
ip netns exec ns1 iptables -t mangle -A DIVERT -j MARK --set-mark 1112
ip netns exec ns1 iptables -t mangle -A DIVERT -j ACCEPT
ip netns exec ns1 iptables -t mangle -A PREROUTING -i veth2 -p udp -j TPROXY --tproxy-mark 1112 --on-ip 10.0.22.1 --on-port 1112
# ip netns exec ns2 dig @1.1.1.1
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out
;; communications error to 1.1.1.1#53: timed out

; <<>> DiG 9.19.25-185-g392e7199df2-1-Debian <<>> @1.1.1.1
; (1 server found)
;; global options: +cmd
;; no servers could be reached
# socks -l -i0.0.0.0 -p1082
240625143739.290 1082 00000 - 0.0.0.0:1082 0.0.0.0:0 0 0 0 Accepting connections [403472/2043553600]
240625143815.419 1082 00100 - 10.0.11.2:45822 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0
240625143820.437 1082 00100 - 10.0.11.2:45836 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0
240625143825.440 1082 00100 - 10.0.11.2:54776 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0
# ip netns exec ns1 /dev/shm/gost -L "redu://10.0.22.1:1112" -F "socks5://10.0.11.1:1082?relay=udp"
{"handler":"redu","kind":"service","level":"info","listener":"redu","msg":"listening on 10.0.22.1:1112/udp","service":"service-0","time":"2024-06-25T10:37:35.961-04:00"}
{"handler":"redu","kind":"listener","level":"info","listener":"redu","msg":"10.0.22.2:40080 >> 1.1.1.1:53","service":"service-0","time":"2024-06-25T10:37:45.403-04:00"}
{"handler":"redu","kind":"handler","level":"info","listener":"redu","local":"1.1.1.1:53","msg":"10.0.22.2:40080 <> 1.1.1.1:53","remote":"10.0.22.2:40080","service":"service-0","time":"2024-06-25T10:37:45.403-04:00"}
{"handler":"redu","kind":"listener","level":"info","listener":"redu","msg":"10.0.22.2:51680 >> 1.1.1.1:53","service":"service-0","time":"2024-06-25T10:37:50.408-04:00"}
{"handler":"redu","kind":"handler","level":"info","listener":"redu","local":"1.1.1.1:53","msg":"10.0.22.2:51680 <> 1.1.1.1:53","remote":"10.0.22.2:51680","service":"service-0","time":"2024-06-25T10:37:50.408-04:00"}
{"handler":"redu","kind":"listener","level":"info","listener":"redu","msg":"10.0.22.2:50017 >> 1.1.1.1:53","service":"service-0","time":"2024-06-25T10:37:55.413-04:00"}
{"handler":"redu","kind":"handler","level":"info","listener":"redu","local":"1.1.1.1:53","msg":"10.0.22.2:50017 <> 1.1.1.1:53","remote":"10.0.22.2:50017","service":"service-0","time":"2024-06-25T10:37:55.413-04:00"}
{"address":"1.1.1.1:53","connector":"socks5","dialer":"tcp","hop":"hop-0","kind":"connector","level":"error","local":"10.0.11.2:45822","msg":"EOF","network":"udp","node":"node-0","remote":"10.0.11.1:1082","time":"2024-06-25T10:38:15.419-04:00"}
{"handler":"redu","kind":"handler","level":"error","listener":"redu","msg":"route(retry=0) EOF","service":"service-0","time":"2024-06-25T10:38:15.419-04:00"}
{"dst":"1.1.1.1:53/udp","handler":"redu","kind":"handler","level":"error","listener":"redu","local":"1.1.1.1:53","msg":"EOF","remote":"10.0.22.2:40080","service":"service-0","time":"2024-06-25T10:38:15.419-04:00"}
{"dst":"1.1.1.1:53/udp","duration":30016023412,"handler":"redu","kind":"handler","level":"info","listener":"redu","local":"1.1.1.1:53","msg":"10.0.22.2:40080 >< 1.1.1.1:53","remote":"10.0.22.2:40080","service":"service-0","time":"2024-06-25T10:38:15.419-04:00"}
{"handler":"redu","kind":"service","level":"error","listener":"redu","msg":"EOF","service":"service-0","time":"2024-06-25T10:38:15.419-04:00"}
{"address":"1.1.1.1:53","connector":"socks5","dialer":"tcp","hop":"hop-0","kind":"connector","level":"error","local":"10.0.11.2:45836","msg":"EOF","network":"udp","node":"node-0","remote":"10.0.11.1:1082","time":"2024-06-25T10:38:20.437-04:00"}
{"handler":"redu","kind":"handler","level":"error","listener":"redu","msg":"route(retry=0) EOF","service":"service-0","time":"2024-06-25T10:38:20.437-04:00"}
{"dst":"1.1.1.1:53/udp","handler":"redu","kind":"handler","level":"error","listener":"redu","local":"1.1.1.1:53","msg":"EOF","remote":"10.0.22.2:51680","service":"service-0","time":"2024-06-25T10:38:20.437-04:00"}
{"dst":"1.1.1.1:53/udp","duration":30028334462,"handler":"redu","kind":"handler","level":"info","listener":"redu","local":"1.1.1.1:53","msg":"10.0.22.2:51680 >< 1.1.1.1:53","remote":"10.0.22.2:51680","service":"service-0","time":"2024-06-25T10:38:20.437-04:00"}
{"handler":"redu","kind":"service","level":"error","listener":"redu","msg":"EOF","service":"service-0","time":"2024-06-25T10:38:20.437-04:00"}
{"address":"1.1.1.1:53","connector":"socks5","dialer":"tcp","hop":"hop-0","kind":"connector","level":"error","local":"10.0.11.2:54776","msg":"EOF","network":"udp","node":"node-0","remote":"10.0.11.1:1082","time":"2024-06-25T10:38:25.441-04:00"}
{"handler":"redu","kind":"handler","level":"error","listener":"redu","msg":"route(retry=0) EOF","service":"service-0","time":"2024-06-25T10:38:25.441-04:00"}
{"dst":"1.1.1.1:53/udp","handler":"redu","kind":"handler","level":"error","listener":"redu","local":"1.1.1.1:53","msg":"EOF","remote":"10.0.22.2:50017","service":"service-0","time":"2024-06-25T10:38:25.441-04:00"}
{"dst":"1.1.1.1:53/udp","duration":30027883955,"handler":"redu","kind":"handler","level":"info","listener":"redu","local":"1.1.1.1:53","msg":"10.0.22.2:50017 >< 1.1.1.1:53","remote":"10.0.22.2:50017","service":"service-0","time":"2024-06-25T10:38:25.441-04:00"}
{"handler":"redu","kind":"service","level":"error","listener":"redu","msg":"EOF","service":"service-0","time":"2024-06-25T10:38:25.441-04:00"}

When using Glider instead of GOST, everything works fine:

# ip netns exec ns2 dig @1.1.1.1

; <<>> DiG 9.19.25-185-g392e7199df2-1-Debian <<>> @1.1.1.1
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9635
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;.              IN  NS

;; ANSWER SECTION:
.           517351  IN  NS  a.root-servers.net.
.           517351  IN  NS  b.root-servers.net.
.           517351  IN  NS  c.root-servers.net.
.           517351  IN  NS  d.root-servers.net.
.           517351  IN  NS  e.root-servers.net.
.           517351  IN  NS  f.root-servers.net.
.           517351  IN  NS  g.root-servers.net.
.           517351  IN  NS  h.root-servers.net.
.           517351  IN  NS  i.root-servers.net.
.           517351  IN  NS  j.root-servers.net.
.           517351  IN  NS  k.root-servers.net.
.           517351  IN  NS  l.root-servers.net.
.           517351  IN  NS  m.root-servers.net.

;; Query time: 199 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Tue Jun 25 10:43:15 EDT 2024
;; MSG SIZE  rcvd: 239
# socks -l -i0.0.0.0 -p1082
240625144313.026 1082 00000 - 0.0.0.0:1082 0.0.0.0:0 0 0 0 Accepting connections [417541/1807640384]
240625144325.027 1082 00000 - 10.0.11.2:53839 1.1.1.1:53 40 239 0 UDPMAP 1.1.1.1:53
# ip netns exec ns1 /opt/glider/glider -verbose -listen tproxy://10.0.22.1:1112 -forward socks5://10.0.11.1:1082
2024/06/25 10:43:10 group.go:191: [group] main: only 1 forwarder found, disable health checking
2024/06/25 10:43:10 server.go:78: [tproxyu] listening UDP on 10.0.22.1:1112
2024/06/25 10:43:14 server.go:155: [tproxyu] 10.0.22.2:49138 <-> 1.1.1.1:53 via 10.0.11.1:1082

For cleaning all the mess: ip link del veth1 ; ip netns del ns1; ip netns del ns2


PS: socks in the command line is a program shipped with 3proxy.

ginuerzh commented 1 week ago

I can't reproduce this problem using your example.

przemyslaw0 commented 1 week ago

I reproduced the same test you mentioned above (with 3proxy):

$ socks -l -p1080
240626213241.032 1080 00000 - 0.0.0.0:1080 0.0.0.0:0 0 0 0 Accepting connections [246504/917522240]
240626213251.098 1080 00000 - 127.0.0.1:36560 127.0.0.1:5201 0 0 0 CONNECT 127.0.0.1:5201

$ /dev/shm/gost -L "socks://:11080?udp=true&notls=true&udpBufferSize=65535" -F "socks://:1080?relay=udp&udpBufferSize=65535"
{"handler":"socks","kind":"service","level":"info","listener":"tcp","msg":"listening on [::]:11080/tcp","service":"service-0","time":"2024-06-26T17:32:45.695-04:00"}
{"handler":"socks","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:11080","msg":"127.0.0.1:49866 <> 127.0.0.1:11080","remote":"127.0.0.1:49866","service":"service-0","time":"2024-06-26T17:32:51.097-04:00"}
{"cmd":"connect","dst":"127.0.0.1:5201/tcp","handler":"socks","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:11080","msg":"127.0.0.1:49866 <-> 127.0.0.1:5201","remote":"127.0.0.1:49866","service":"service-0","time":"2024-06-26T17:32:51.098-04:00"}
{"cmd":"connect","dst":"127.0.0.1:5201/tcp","duration":108549,"handler":"socks","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:11080","msg":"127.0.0.1:49866 >-< 127.0.0.1:5201","remote":"127.0.0.1:49866","service":"service-0","time":"2024-06-26T17:32:51.098-04:00"}
{"duration":605524,"handler":"socks","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:11080","msg":"127.0.0.1:49866 >< 127.0.0.1:11080","remote":"127.0.0.1:49866","service":"service-0","time":"2024-06-26T17:32:51.098-04:00"}

$ /dev/shm/gost -L tcp://:15201/:5201 -L "udp://:15201/:5201?keepalive=true&readBufferSize=65535" -F "socks5://:11080?relay=udp&udpBufferSize=65535"
{"handler":"tcp","kind":"service","level":"info","listener":"tcp","msg":"listening on [::]:15201/tcp","service":"service-0","time":"2024-06-26T17:32:48.503-04:00"}
{"handler":"udp","kind":"service","level":"info","listener":"udp","msg":"listening on [::]:15201/udp","service":"service-1","time":"2024-06-26T17:32:48.503-04:00"}
{"handler":"tcp","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:15201","msg":"127.0.0.1:42068 <> 127.0.0.1:15201","remote":"127.0.0.1:42068","service":"service-0","time":"2024-06-26T17:32:51.097-04:00"}
{"dst":":5201/tcp","handler":"tcp","host":":0","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:15201","msg":"127.0.0.1:42068 <-> :5201","node":"target-0","remote":"127.0.0.1:42068","service":"service-0","time":"2024-06-26T17:32:51.098-04:00"}
{"dst":":5201/tcp","duration":228745,"handler":"tcp","host":":0","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:15201","msg":"127.0.0.1:42068 >-< :5201","node":"target-0","remote":"127.0.0.1:42068","service":"service-0","time":"2024-06-26T17:32:51.098-04:00"}
{"dst":":5201/tcp","duration":986628,"handler":"tcp","host":":0","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:15201","msg":"127.0.0.1:42068 >< 127.0.0.1:15201","node":"target-0","remote":"127.0.0.1:42068","service":"service-0","time":"2024-06-26T17:32:51.098-04:00"}

$ iperf3 -c 127.0.0.1 -p 15201 -u
iperf3: error - control socket has closed unexpectedly

It doesn't work, but ok, I tried to debug with Dante (one of most used SOCKS5 servers), and also another less known SOCKS5 server called hev-socks5-server:

Here is the Dante configuration:

logoutput: /dev/shm/log
user.privileged: root
user.unprivileged: nobody
user.libwrap: nobody
debug: 2
internal.protocol: ipv6 ipv4
internal: 0.0.0.0 port = 1082
external: lo
socksmethod: none
clientmethod: none

client pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    socksmethod: none
    log: connect disconnect error ioop data tcpinfo
}
socks pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    log: connect disconnect error ioop data tcpinfo
    protocol: tcp udp
    socksmethod: none
    command: bind connect udpassociate
}

Dante log: https://paste.ee/p/A6MAk

The strange lines I can see in the Dante log are:

[...]
Jun 26 17:41:15 (1719438075.411714) danted[246900]: debug: reqhostisok(): host .0, command udpassociate
Jun 26 17:41:15 (1719438075.411717) danted[246900]: debug: set_hints_ai_family: ai_family = 0
Jun 26 17:41:15 (1719438075.411726) danted[246900]: debug: int_sockshost2sockaddr2(): could not resolve hostname "": Name or service not known
Jun 26 17:41:15 (1719438075.411728) danted[246900]: debug: loglevel_gaierr(): error -2, side internal
Jun 26 17:41:15 (1719438075.411731) danted[246900]: debug: could not DNS-resolve "": Name or service not known
Jun 26 17:41:15 (1719438075.411736) danted[246900]: info: block(1): udp/udpassociate ]: 127.0.0.1.42004 127.0.0.1.1080: could not resolve hostname "": Name or service not known
[...]
Jun 26 17:41:15 (1719438075.411790) danted[246900]: info: block(1): tcp/accept ]: 127.0.0.1.42004 127.0.0.1.1080: request was not performed due to error: could not resolve hostname "": Name or service not known
[...]
Jun 26 17:41:20 (1719438080.766702) danted[246916]: info: pass(1): tcp/accept ]: 2 -> 127.0.0.1.41988 127.0.0.1.1080 -> 187: local client closed.  Session duration: 5s
[...]

When using Dante to debug the test I posted above with network namespaces I can see this:

[...]
Jun 26 15:29:44 (1719430184.035928) danted[155262]: debug: reqhostisok(): host .0, command udpassociate
[...]
Jun 26 15:29:44 (1719430184.037910) danted[155262]: debug: cgetaddrinfo(): getaddrinfo(, <NULL>, { ai_flags: 0, ai_family: 0, ai_socktype: 0, ai_protocol: 0 }) returned -2 and (nil): Name or service not known
Jun 26 15:29:44 (1719430184.037923) danted[155262]: debug: int_sockshost2sockaddr2(): could not resolve hostname "": Name or service not known
Jun 26 15:29:44 (1719430184.037926) danted[155262]: debug: loglevel_gaierr(): error -2, side internal
Jun 26 15:29:44 (1719430184.037929) danted[155262]: debug: could not DNS-resolve "": Name or service not known
Jun 26 15:29:44 (1719430184.037954) danted[155262]: info: block(1): udp/udpassociate ]: 127.0.0.1.44124 127.0.0.1.1082: could not resolve hostname "": Name or service not known
[...]
Jun 26 15:29:49 (1719430189.040098) danted[155262]: debug: int_sockshost2sockaddr2(): could not resolve hostname "": Name or service not known
Jun 26 15:29:49 (1719430189.040101) danted[155262]: debug: loglevel_gaierr(): error -2, side internal
Jun 26 15:29:49 (1719430189.040105) danted[155262]: debug: could not DNS-resolve "": Name or service not known
Jun 26 15:29:49 (1719430189.040112) danted[155262]: info: block(1): udp/udpassociate ]: 127.0.0.1.44126 127.0.0.1.1082: could not resolve hostname "": Name or service not known
[...]
Jun 26 15:29:49 (1719430189.040224) danted[155262]: info: block(1): tcp/accept ]: 127.0.0.1.44126 127.0.0.1.1082: request was not performed due to error: could not resolve hostname "": Name or service not known
[...]
Jun 26 15:29:54 (1719430194.042182) danted[155262]: debug: reqhostisok(): host .0, command udpassociate
Jun 26 15:29:54 (1719430194.042186) danted[155262]: debug: set_hints_ai_family: ai_family = 0
Jun 26 15:29:54 (1719430194.042196) danted[155262]: debug: int_sockshost2sockaddr2(): could not resolve hostname "": Name or service not known
Jun 26 15:29:54 (1719430194.042201) danted[155262]: debug: loglevel_gaierr(): error -2, side internal
Jun 26 15:29:54 (1719430194.042204) danted[155262]: debug: could not DNS-resolve "": Name or service not known
Jun 26 15:29:54 (1719430194.042211) danted[155262]: info: block(1): udp/udpassociate ]: 127.0.0.1.34370 127.0.0.1.1082: could not resolve hostname "": Name or service not known
[...]
Jun 26 15:29:54 (1719430194.042306) danted[155262]: info: block(1): tcp/accept ]: 127.0.0.1.34370 127.0.0.1.1082: request was not performed due to error: could not resolve hostname "": Name or service not known
[...]

Here is the hev-socks5-server log: https://paste.ee/p/AVw40

You can see this line:

[2024-06-26 16:21:06] [I] 0x7df398001770 socks5 server resolve []:0

3proxy cannot decode the destination address too:

# socks -l -i0.0.0.0 -p1082
240625143739.290 1082 00000 - 0.0.0.0:1082 0.0.0.0:0 0 0 0 Accepting connections [403472/2043553600]
240625143815.419 1082 00100 - 10.0.11.2:45822 0.0.0.0:0 0 0 0 UDPMAP 0.0.0.0:0

Resuming: The SOCKS5 servers (except by Glider and Bridge until now) cannot decode the target address.

What I suspect, is that GOST (or maybe the Go standard library) is sending the UDP destination address in an encoding format other than ASCII, like UTF-8, perhaps can explain that Glider can decode the destination address, and Glider is made in Go.

My Linux system is in fully English with the standard locale as "en-US", you should use another encoding in your system where you tested and it worked, perhaps can explain why it worked for and not for me.

ginuerzh commented 1 day ago

I made a mistake and forgot to update a dependency package, please try the latest version again.

przemyslaw0 commented 1 day ago

I tested, now it works with hev-socks5-tproxy, but doesn't with 3proxy when the UDP address is IPv6:

$ host g.co 2606:4700:4700::1001
;; communications error to 2606:4700:4700::1001#53: timed out
;; communications error to 2606:4700:4700::1001#53: timed out
;; no servers could be reached

$ host g.co 2620:fe::9
;; communications error to 2620:fe::9#53: timed out
;; communications error to 2620:fe::9#53: timed out
;; no servers could be reached
$ socks -l -p1112
240704204343.795 1112 00000 - 0.0.0.0:1112 0.0.0.0:0 0 0 0 Accepting connections [263362/667100992]
240704204353.240 1112 00000 - 127.0.0.1:53080 4700::1001:0:0:53 22 0 0 UDPMAP 0.0.0.0:0
240704204358.244 1112 00000 - 127.0.0.1:49934 4700::1001:0:0:53 22 0 0 UDPMAP 0.0.0.0:0
240704204408.384 1112 00000 - 127.0.0.1:52194 ::9:0:0:53 22 0 0 UDPMAP 0.0.0.0:0
240704204413.388 1112 00000 - 127.0.0.1:52200 ::9:0:0:53 22 0 0 UDPMAP 0.0.0.0:0
# /dev/shm/gost/cmd/gost/gost -L "socks5://127.0.0.1:1111?udp=true" -F "socks5://127.0.0.1:1112?relay=udp"
{"handler":"socks5","kind":"service","level":"info","listener":"tcp","msg":"listening on 127.0.0.1:1111/tcp","service":"service-0","time":"2024-07-04T16:45:01.194-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:49927 <> 127.0.0.1:1111","remote":"127.0.0.1:49927","service":"service-0","time":"2024-07-04T16:45:06.598-04:00"}
{"duration":5002350552,"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:49927 >< 127.0.0.1:1111","remote":"127.0.0.1:49927","service":"service-0","time":"2024-07-04T16:45:11.600-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:41799 <> 127.0.0.1:1111","remote":"127.0.0.1:41799","service":"service-0","time":"2024-07-04T16:45:11.600-04:00"}
{"duration":5003660036,"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:41799 >< 127.0.0.1:1111","remote":"127.0.0.1:41799","service":"service-0","time":"2024-07-04T16:45:16.604-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:41525 <> 127.0.0.1:1111","remote":"127.0.0.1:41525","service":"service-0","time":"2024-07-04T16:45:21.532-04:00"}
{"duration":5004930855,"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:41525 >< 127.0.0.1:1111","remote":"127.0.0.1:41525","service":"service-0","time":"2024-07-04T16:45:26.537-04:00"}
{"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:41413 <> 127.0.0.1:1111","remote":"127.0.0.1:41413","service":"service-0","time":"2024-07-04T16:45:26.537-04:00"}
{"duration":5002836397,"handler":"socks5","kind":"handler","level":"info","listener":"tcp","local":"127.0.0.1:1111","msg":"127.0.0.1:41413 >< 127.0.0.1:1111","remote":"127.0.0.1:41413","service":"service-0","time":"2024-07-04T16:45:31.540-04:00"}
^C{"handler":"socks5","kind":"service","level":"error","listener":"tcp","msg":"accept: accept tcp4 127.0.0.1:1111: use of closed network connection","service":"service-0","time":"2024-07-04T16:45:41.826-04:00"}

You can see that the address received by 3proxy is incomplete, maybe something is missing in the dialer (bracket?).

Just a suggestion, you could implement support for specifying network namespaces in the GOST config by path, for example /proc/1/ns/net

When I need to select the netns of PID 1 (host namespace) inside a secondary netns, I have to do this:

sudo ln -s /proc/1/ns/net /var/run/netns/out