3

I got the inspiration here. It looks like AFWall+ is able to create a NAT forwarding policy to keep all traffic going through a SOCKS5 proxy and fool Google apps into thinking they are not connected via a VPN (Google apps implement additional security measures when connecting via VPNService and if you are in China you will not pass the security check - the security check requests don't go through VPN, so they will EOF because GFW will kill these requests, read more here).

So my question is, if let's say I have a socks5 server running at 192.168.1.1:1088 which tunnels all connections via vmess protocol (aka V2Ray) to remote servers in the US, how do I create my custom script? I have tried:

IP6TABLES=/system/bin/ip6tables
IPTABLES=/system/bin/iptables
ULIMIT=/system/bin/ulimit
PORT=1088
SERVER=192.168.1.1
$ULIMIT -n 4096
$IP6TABLES -F
$IP6TABLES -A INPUT -j DROP
$IP6TABLES -A OUTPUT -j DROP
$IPTABLES -t nat -F OUTPUT
$IPTABLES -t nat -A OUTPUT -o lo -j RETURN
$IPTABLES -t nat -A OUTPUT -d 127.0.0.1 -j RETURN
$IPTABLES -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination $SERVER:$PORT
$IPTABLES -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination $SERVER:$PORT
$IPTABLES -t nat -A OUTPUT -p tcp -j DNAT --to-destination $SERVER:$PORT
$IPTABLES -t nat -A OUTPUT -p udp -j DNAT --to-destination $SERVER:$PORT

This does not work. So:

  1. Did I create a wrong script? How do I create a script that does what I want to do?
  2. Are there other settings that I should enable first? I didn't tick any app so I assume that means all app go through custom script, right?
4

The link you have provided is not setting up SOCKS but a transparent proxy i.e. it takes TCP/UDP traffic and SOCKSify it before sending through shadowsocks tunnel. But you need to make your traffic SOCKS-aware before directing towards SOCKS proxy. Either configure individual apps (which have built-in support for SOCKS) or enforce proxy system-wide transparently (what you are trying to do).

LIMITATIONS OF SOCKS PROXY:

It looks like AFWall+ is able to create a NAT forwarding policy

AFWall+ uses iptables at back end and it can execute your script on network changes. Enforcing global proxy is (at least partially) possible with proxifier apps like ProxyDroid (which is iptables-based) and SocksDroid (which is VPN/routing based). I have no affiliation with either.

If manually workig from CLI, you can use a transparent TCP/UDP-to-proxy redirector like redsocks in combination with iptables. shadowsocks provides its own similar tool (ss-redir), so does Tor.

I didn't tick any app so I assume that means all app go through custom script, right?

No. The problem with the iptables approach is that SOCKS5 is a layer 5 protocol in OSI model. So it cannot carry whole traffic from all apps. Most of the traffic generated by apps is TCP which works fine with SOCKS and is easy to setup. But some games, VoIP apps and above all the traditional DNS generate UDP traffic which is not supported by many SOCKS5 proxies. E.g. openssh and tor both don't, shadowsocks however does have UDP associate features. But it doesn't work with simple DNAT or REDIRECT (probably because SO_ORIGINAL_DST is not available for UDP sockets, I don't know the details). You can possibly redirect traffic only towards a fixed socket (IP:PORT) e.g. a DNS server or game server.

TPROXY is the alternative here, but the trouble is that it works only with PREROUTING chain i.e. the traffic coming from outside, not that generated on device. So you have to do extra setup to route your on-device traffic without NATing towards a local proxy server (usually default gateway) where you'll set up TPROXY.

Complicated? That's why VPN is preferred. Even if you need to use a proxy to circumvent firewalls, VPN tunneling through proxy spares you from the traffic redirection complexities. VPN operates at lower level in network stack (L2/L3 in OSI), so it flawlessly carries all IP traffic including ICMP echos (ping) etc. which can no way be sent through SOCKS. Another plus point is that VPN can be tunneled through transparent proxies - like shapeshifter-dispatcher and stunnel - or SOCKS proxies which are meant to forward only single port - like obfs4proxy.

If not forwarding single port (tunneling), SOCKS5 must be an application level proxy i.e. it should be able to forward arbitrary ports from different apps like SSH dynamic port forwarding does.

tun2socks is another SOCKSification method which collects TCP/UDP traffic on a tun interface (same like a VPN, no NAT involved) and forwards it through a SOCKS proxy. It recently added UDP associate support. Previously used UDP Gateway method also worked quite fine but it requires running a separate daemon (udpgw) along with proxy server. tun2socks is a non-root solution because apps - like SocksDroid and many other firewalls, sniffers etc. - using this method rely on Android's VPN facilities.

... and fool Google apps into thinking they are not connected via a VPN (Google apps implement additional security measures when connecting via VPNService ...

With both above methods (VPN through tunnel and Tun-to-SOCKS) it's not necessary to use Android's VPNService API (if that's causing problems for you). On a rooted device you can get a static openvpn or tun2socks binary and run that through CLI. That's far less hassle than setting up proxy through iptables. In former case, though, you need a VPN server obviously.

SOCKSIFY WHOLE DEVICE:

As you don't want to go with VPN/routing based solution, here is the simple iptables-based method.

First get redsocks binary for your device architecture (or try this one for aarch64 or this one for armeabi-v7a). Create configuration file:

// redsocks.conf

// general configuration
base {
    redirector = iptables;
}

// for TCP
redsocks {
    local_ip = "127.0.0.1"; local_port = "12345";
    ip = "192.168.1.1"; port = "1088"; type = socks5;
}

// for UDP, assuming your SOCKS5 proxy supports UDP associate
redudp {
    local_ip = "127.0.0.1"; local_port = "12345";
    ip = "192.168.1.1"; port = "1088";
    dest_ip = "1.1.1.1"; dest_port = "53";  /* set whatever DNS server */
}

* See redsocks.conf.example for details and more options.

Run:

#!/system/bin/sh

IPTABLES="/system/bin/iptables -w5 -t nat"

# create new chain
$IPTABLES -N PROXY
$IPTABLES -I OUTPUT -j PROXY

# exclude local traffic, see: http://manpages.org/ss-redir
$IPTABLES -A PROXY -d 127.0.0.0/8 -j RETURN
$IPTABLES -A PROXY -d 192.168.0.0/16 -j RETURN

# socksify whole TCP traffic
$IPTABLES -A PROXY -p tcp -j DNAT --to 127.0.0.1:12345

# socksify only DNS UDP traffic
$IPTABLES -A PROXY -p udp --dport 53 -j DNAT --to 127.0.0.1:12345

echo "Ctrl^C to exit."
trap "$IPTABLES -D OUTPUT -j PROXY; $IPTABLES -F PROXY; $IPTABLES -X PROXY" EXIT

# run socksifier
redsocks -c /path/to/redsocks.conf

You can add custom iptables script to AFWall+. redsocks can be run as init service with non-root UID, dropped capabilities and restricted SELinux context. See How to run an executable on boot?


RELATED:

| improve this answer | |
  • Your redsocks + iptables solution worked but I had to correct several things to use Dante SOCKS proxy on Anbox. For the first iptables command, I got error unknown option "-w5". Adding a space before the number did not solve the problem. Anbox used Android 7 (x86) with iptables v1.4.20 and the -w parameter did not accept any value. Is this parameter necessary? I did not need to use it. Then I had to comment the iptables command for UDP, otherwise DNS would not work. In redsocks.conf, I also had to comment the redudp block because of the error file parsing error at line 13: unknown section. – baptx Apr 18 at 21:37
  • @baptx for -w see iptables manpage. // UDP is officially supported by redsocks: github.com/darkk/redsocks/blob/master/…. It doesn't work for you because your proxy doesn't have UDP associate feature. So you can't send DNS or any other UDP traffic through proxy. That's what I've explained under LIMITATIONS OF SOCKS PROXY. Please go through the answer completely for better understanding. // May be you need an empty line at .conf end: github.com/darkk/redsocks/issues/134 – Irfan Latif Apr 19 at 3:45
  • I still got the file parsing error on the redudp line, even with an empty line at the end of the config file. It looks like this configuration is not supported by the version of redsocks I am using. I downloaded the x86 build of redsocks from ProxyDroid. With redsocks -v, I can see that they are using an older version, 0.4 instead of latest 0.5. – baptx Apr 19 at 9:45
  • 1
    @baptx UDP is supported since version 0.1: github.com/darkk/redsocks/commit/…. But you may consider building from latest source. – Irfan Latif Apr 19 at 10:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.