Skip to content
This repository has been archived by the owner on Aug 22, 2021. It is now read-only.

Implement optional support for SOCKS5-UDP #71

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

bemasc
Copy link
Contributor

@bemasc bemasc commented Dec 14, 2018

This change adds a new option, --socks5-udp. If this option is
present, and no UDP gateway is specified, UDP packets will no
longer be dropped. Instead, the client will use the SOCKS5
UDP ASSOCIATE command to route UDP packets through the proxy
server.

This implementation is intended for use with any UDP data, and it
includes an optimization for packets containing DNS queries.
However, this implementation is currently limited to localhost
SOCKS5 servers. SOCKS5-UDP does not perform well over actual
network links, as it requires several roundtrips to the server and
is not compatible with NAT.

This implementation is currently in use in a fork of tun2socks used
by Outline (https://getoutline.org) and Intra (https://getintra.org).

Fixes #56

@4-FLOSS-Free-Libre-Open-Source-Software

great, well i couldn't built it in windows?

@bemasc
Copy link
Contributor Author

bemasc commented Jan 1, 2019

What error message do you see? Building for Windows worked for me using Cygwin.

@4-FLOSS-Free-Libre-Open-Source-Software

sorry i tried MSVC which didn't compile in your branch but master. actually i wasn't able to compile in windows with cygwin at all. so i don't want to blame the udp feature for this. but would like to test this.

This change adds a new option, --socks5-udp.  If this option is
present, and no UDP gateway is specified, UDP packets will no
longer be dropped.  Instead, the client will use the SOCKS5
UDP ASSOCIATE command to route UDP packets through the proxy
server.

This implementation is intended for use with any UDP data, and it
includes an optimization for packets containing DNS queries.
However, this implementation is currently limited to localhost
SOCKS5 servers. SOCKS5-UDP does not perform well over actual
network links, as it requires several roundtrips to the server and
is not compatible with NAT.

This implementation is currently in use in a fork of tun2socks used
by Outline (https://getoutline.org) and Intra (https://getintra.org).

Fixes ambrop72#56
@bemasc
Copy link
Contributor Author

bemasc commented Jan 15, 2019

@4-FLOSS-Free-Libre-Open-Source-Software Thanks for reporting the error on Windows. I rebased this branch on @ambrop72's latest Windows build improvements, and I was able to reproduce the failure. The problem I saw was that SocksUdpClient.c was using some C99 syntax that is not supported by MSVC.

I've removed the use of non-MSVC-compatible syntax from SocksUdpClient.c, and verified that this branch now builds on linux with gcc and on Windows with MSVC using the new instructions.

This branch should be ready to merge.

@ambrop72
Copy link
Owner

Cool that this is fixed. I will try to find time to review this pull request.

@4-FLOSS-Free-Libre-Open-Source-Software

@4-FLOSS-Free-Libre-Open-Source-Software Thanks for reporting the error on Windows. verified that this branch now builds on linux with gcc and on Windows with MSVC

me too can confirm it builds fine, good job @bemasc

@ambrop72
Copy link
Owner

ambrop72 commented Aug 6, 2019

Could you please add a copyright notice to SocksUdpClient.h/c, i.e. "Copyright (C) your_name_or_company", above the license terms text?

@bemasc
Copy link
Contributor Author

bemasc commented Aug 19, 2019

Done!

@ambrop72
Copy link
Owner

Thanks. I have already reviewed the other code, when I'm done with those last files I will merge with some fixups.

@ioxuy
Copy link

ioxuy commented Aug 27, 2019

Done!

test failed,what did I do wrong?

working.
QQ截图20190827164138

failed
QQ截图20190827164034

failed
QQ截图20190827164945

@4-FLOSS-Free-Libre-Open-Source-Software

@ioxuy could you get past the assertion errors until now?
do you use ipv6 udp traffic on tapinterface no or? i only see ipv4 interface configured.
line 119 i don´t get it.

} break;

@ambrop72
Copy link
Owner

ambrop72 commented Dec 2, 2019

@bemasc, I have some comments/questions.

However, this implementation is currently limited to localhost
SOCKS5 servers. SOCKS5-UDP does not perform well over actual
network links, as it requires several roundtrips to the server and
is not compatible with NAT.

The round-trip should not be too bad for local (non-Internet links).

From reading the code, it seems that the localhost-only limitation is because the UDP socket is always bound to a localhost address, and this is the address sent to the SOCKS server as DST.ADDR. Anyway, I think instead of binding to localhost, we should do one of the following, selected via command line flags:

  1. Send zeros in DST.ADDR (allowed by the SOCKS5 RFC) and do not bind the UDP socket; let the kernel assign the local address when the first packet is sent. I think this has the best chance of working when NAT is involved.
  2. Get the local address of the TCP socket used for the SOCKS server and bind to some port on that address. This should work when the SOCKS server, UDP relay and tun2socks are not separated by NAT (and the UDP relay is not on a different network interface than the SOCKS server, which would be really strange).

You don't need to change the code, I plan to improve it, I'd just like to hear your reasoning and if you think the above would work.

@bemasc
Copy link
Contributor Author

bemasc commented Dec 2, 2019

Those options both seem reasonable to me. I don't know whether most SOCKS-UDP servers implement correct support for zero DST.ADDR, but having a user control to choose that option seems like a fine idea. For simplicity, you might want to use the #2 binding behavior in both cases, so the only thing that changes between the modes is the value of DST.ADDR. As you mentioned, this should work fine so long as the UDP and TCP proxies are routable from the same interface, which seems like a reasonable assumption*.

Just make sure to drop any downstream UDP packets whose source address doesn't match BND.ADDR, and also be careful when parsing the matching packets due to source-IP spoofing.

*One case where this would fail is TCP reverse-binding a remote SOCKS server onto localhost (e.g. with ssh -L). I think it's fine not to support that, at least initially.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

How can I add standard socks Udp Associate feature into this tun2socks?
4 participants