ShadowsocksR-Live / shadowsocksr-native

翻墙 从容穿越党国敏感日 ShadowsocksR (SSRoT) native implementation for all platforms, GFW terminator
https://github.com/ShadowsocksR-Live/shadowsocksr-native/wiki
GNU General Public License v3.0
2.74k stars 763 forks source link

UDP relay implementation does not honor SOCK5 RFC #242

Open siwliu-kernel opened 1 year ago

siwliu-kernel commented 1 year ago

A openvpn client has the following config in /etc/openvpn/client/client.conf:

remote 111.111.111.111 1194 udp
route 111.111.111.111 255.255.255.255 10.0.0.1
socks-proxy 127.0.0.1 1080

Launch this openvpn client over SSRoT ends up with below error:

# openvpn --suppress-timestamps --nobind --config /etc/openvpn/client/client.conf
:
:
TCP/UDP: Preserving recently used remote address: [AF_INET]127.0.0.1:1080
Attempting to establish TCP connection with [AF_INET]127.0.0.1:1080 [nonblock]
TCP connection established with [AF_INET]127.0.0.1:1080
UDP link local: (not bound)
UDP link remote: [AF_INET]111.111.111.111:1194
TCP/UDP: Incoming packet rejected from [AF_INET]127.0.0.1:57477[2], expected peer address: [AF_INET]111.111.111.111:1194 (allow this incoming source address/port by removing --remote or adding --float)
TCP/UDP: Incoming packet rejected from [AF_INET]127.0.0.1:57477[2], expected peer address: [AF_INET]111.111.111.111:1194 (allow this incoming source address/port by removing --remote or adding --float)

UDP socket 127.0.0.1:57477 was opened by openvpn client to get the response from openvpn server 111.111.111.111:1194 through ssr-client's udp relay:

Jan 1 00:00:51 hostname ssr-client[6122]: #033[0mssr-client 2023/01/01 00:00 info #033[0m[udp] 127.0.0.1:57477 ==> 111.111.111.111:1194 incoming data from lower-level app, length = 24 Jan 1 00:00:51 hostname ssr-client[6122]: #033[0mssr-client 2023/01/01 00:00 info #033[0m[udp] 127.0.0.1:57477 <== 111.111.111.111:1194 write back received data length = 26 Jan 1 00:00:51 hostname ssr-client[6122]: #033[0mssr-client 2023/01/01 00:01 info #033[0m[udp] 127.0.0.1:57477 ==> 111.111.111.111:1194 incoming data from lower-level app, length = 24 Jan 1 00:00:51 hostname ssr-client[6122]: #033[0mssr-client 2023/01/01 00:01 info #033[0m[udp] 127.0.0.1:57477 <== 111.111.111.111:1194 write back received data length = 22

The error reported by openvpn is because _udp_relay_senddata() doesn't fill _targetaddr to the DST.ADDR field (techinicallly it would be the source address for the original UDP packet where ssr-server had gotten in the first place) in udp relay header per the SOCKS5 RFC spec.

https://github.com/ShadowsocksR-Live/shadowsocksr-native/blob/81a95452ae681a90e672979905b80767e7e2c8f3/src/client/client.c#L1481-L1491

_targetaddr can be passed in _udp_relay_senddata() to replace s5addr: https://github.com/ShadowsocksR-Live/shadowsocksr-native/blob/b39d0cfe760232fa1cfc7824917b8373fc86acc6/src/udprelay.c#L600

_uv_udpsend() should still use _srcaddr as is: https://github.com/ShadowsocksR-Live/shadowsocksr-native/blob/b39d0cfe760232fa1cfc7824917b8373fc86acc6/src/udprelay.c#L605

siwliu-kernel commented 1 year ago

I've verified that openvpn works back fine after changing the above lines of code as indicated. I haven't checked if the other client for e.g. Windows, iOS or Android has similar issue. I'd leave it to @ssrlive to decide.

The ideal solution is to get the corresponding source address for the UDP response packet from the ssr-server, though. A target server could be multi-homed that the UDP response packet may not neccessarily come from the orginal IP address the UDP request was sent to.

ssrlive commented 1 year ago

Yes. but I have no plan to correct the issues. Please play my new toy overtls which support UDP relay very fine.