Skip to content

Instantly share code, notes, and snippets.

@softmoth
Last active July 6, 2023 07:51
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save softmoth/039e2879198f298a41f0924f9fd357c2 to your computer and use it in GitHub Desktop.
Using a proxy to avoid tether throttling

Using a proxy to avoid tether throttling

I use used to use my mobile phone for internet access. My provider's Unlimited data plan discouragesd tethering (using the phone as a hotspot), though, by throttling traffic it sees coming from other devices.

A fairly simple and robust solution is was to run a proxy server on the phone, and then set up the router to send all traffic through the proxy.

Bit rot warning

I no longer use this setup, and do not have access to the mobile account or router that is described here. The comments section below may have further updates. If you can suggest improvements I will integrate them into the gist, but am not able to troubleshoot or verify changes.

Run a proxy on the phone

There are several apps in the Play store which can do this on a stock phone (root not required). I've used Socks Server Ultimate. It's best to get this running first, and manually configure the browser on your laptop to use it, to verify that it's working properly. Then procede to the router setup.

Tethering the router to the phone

On my TP-Link Archer C7 1750 router, I can use the 5Ghz radio as a client to talk to my phone, and the 2.4Ghz radio as the access point. OpenWRT makes it easy to configure via the Scan button in the UI.

If your phone has locked down Hotspot, you may be able to install adb tools and run adb forward tcp:12345 tcp:12346 on the router to forward traffic from the router's port 12345 to the proxy running on the phone's port 12346.

Redirect all traffic to the proxy

I use redsocks and iptables to send all the traffic on the router to the SOCKS5 proxy running on the phone.

I use OpenWRT on my router, but any OS that lets you run redsocks should do fine. For OpenWRT, opkg install redsocks gets it done.

Edit /etc/redsocks.conf to have this:

// send all traffic to a remote SOCKS5 proxy

base {
    log_info = on;
    log = "file:/var/log/proxy_vpn.log";
    daemon = on;
    redirector = iptables;
}

redsocks {
    // Use iptables to redirect traffic here
    local_ip = 0.0.0.0;
    local_port = 12345;

    // Remote proxy info
    // Use 127.0.0.1 if using adb forward; otherwise use the
    // Phone's hotspot IP
    ip = 192.168.43.1;
    port = 12346;
    type = socks5;
}

The package should automatically install /etc/init.d/redsocks and enable it in /etc/rc.d so it will run when the router boots up.

Next, put the following in /etc/init.d/proxy_vpn:

#! /bin/sh /etc/rc.common

# Modified from https://github.com/darkk/redsocks#iptables-example
# Tested on OpenWRT 18.06, TP-LINK Archer C7 v2.0, redsocks 0.4
# Prereq: opkg install redsocks

START=91
REDSOCKS_PORT=37419

start () {
    # Redsocks should be running already, but just in case...
    /etc/init.d/redsocks start

    #
    # Set up iptables
    #

    echo "Routing traffic to redsocks on port $REDSOCKS_PORT"

    #
    # Create the chain of rules to send non-local traffic through redsocks
    #

    iptables -t nat -N REDSOCKS

    # Don't proxy local or private traffic
    iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
    iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
    iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
    iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
    iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

    # Send everything else through the redsocks daemon
    iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports $REDSOCKS_PORT


    #
    # Jump to the REDSOCKS chain if packet is going out on wlan (to phone)
    #

    iptables -t nat -A PREROUTING -i br-lan -p tcp -j REDSOCKS
    # XXX It seems that OUTPUT is too late?
    #iptables -t nat -A OUTPUT -o wlan0 -p tcp -j REDSOCKS
}

stop () {
    iptables -t nat -F REDSOCKS
    iptables -t nat -F PREROUTING
    iptables -t nat -F POSTROUTING
    iptables -F INPUT
    iptables -F FORWARD
    iptables -t nat -X REDSOCKS
    /etc/init.d/firewall restart
}

restart () {
    stop
    start
}
@kickturn
Copy link

Is there any way to do it without a router and straight to like a laptop? this seems interesting.

I've been googling so far but this is the best I can find but I would like to eliminate the use of a router

@kickturn
Copy link

Is there any way to do it without a router and straight to like a laptop? this seems interesting.

I've been googling so far but this is the best I can find but I would like to eliminate the use of a router

Just found the answer for my question, see https://superuser.com/questions/1541255/how-can-i-share-my-unrooted-android-devices-internet-connection-with-my-linux-m

@softmoth
Copy link
Author

Thanks

@cubeuser11
Copy link

cubeuser11 commented Mar 17, 2021

I have installed socks server ultimate and created a server named server with the port on 8022
I tried to ssh from my windows pc to 192.168.113.153 (which is my wlan1) at port 8022 on my bitvise ssh client.
I get an error saying

the SSH session has terminated with error. Reason: FlowSocketReader: Error receiving bytes. Windows error 10054: An existing connection was forcibly closed by the remote host

Then I check the logs on the socks server ultimate app and it says this:

192.168.113.69 - Authentication failed...

192.168.113.69 - New request...

Listening for connections (port:8022)

I'm not exactly sure what I'm supposed to do. Do I have to create a socks server on top of the proxy? And then connect to that socks after I SSH into the proxy on my computer?

I did manage to get it to work on termux by using sshd -dD and then connecting to the listening port on 8080 using bitvise with socks/http proxy forwarding enabled with listen interface at 127.0.0.1 and listen port at 1080. Then setting the global proxy setting on my windows PC to 127.0.0.1:1080. And it worked. But I don't know how to incorporate that into openWRT stuff you posted.

I would very much like to get my hotspot to linkup with the router instead.

@softmoth
Copy link
Author

The Socks Server Ultimate app runs a SOCKS5 proxy. It is running on the phone (or other hotspot device, I suppose), which has direct internet access. You can verify that much is working by setting up your web browser on your laptop to use it. In Firefox, that's under Preferences ... General ... Network Settings. Select "Manual proxy" and put your hotspot's IP in "SOCKS Host", and make sure it's set to SOCKS5. It's not an SSH proxy, so SSH to the port won't work, if I understand you correctly.

The router portion requires that your router can both talk to the hotspot and also talk to normal wifi clients on the wifi LAN. Some routers can do this with two radios, or maybe you can do it by talking to your phone with adb over USB.

The redsocks program, running on the router, hijacks traffic sent on the router and forwards it back and forth to the SOCKS5 proxy. Just like the browser on your laptop does. So if the laptop browser isn't using the Socks Server Ultimate proxy correctly, then redsocks won't be able to either.

It took me quite a lot of fiddling to get it set up and working correctly. Since you're using a significantly different setup than I did, you might need some different settings in either redsocks.conf or iptables. But hopefully with enough tinkering it might work. I no longer use this setup, nor have access to the hardware or cell phone account, so I am limited in what I can help with. I wish you good luck!

@cubeuser11
Copy link

cubeuser11 commented Mar 19, 2021

thank you for the explanation. I somehow stumbled into a solution. I prefer to have developers option and root disabled on my phone for security concerns so it is I think impossible for me to make the hotspot ip assignment static without root. And because new IP is assigned every time I turn on/off the hotspot, I would have to edit the openwrt configuration everytime. There is an app called "proxy server" which lets me create a socks5 proxy server and it displays the newly assigned hotspot ip conveniently and you can just click on the ip instead of typing it out like you would need to with socks server ultimate.

this was my solution for anyone else reading it.
Turn on your vpn on your phone. Use the dhcp assigned IP address for the VPN as the socks5 proxy server address and pick a random port like 12346. ("Proxy server" App should automatically display the IP assigned for VPN, just click on it). Go to your windows PC and connect to the hotspot. Go to network settings -> advanced -> sharing. And allow sharing of the internet from this network with the "Local Area Connection". I also enabled "allow LAN traffic" on my vpn app. Then you can use the socks server address hosted on your android and use it on firefox or global proxy settings or what ever program you need to use. I haven't figured out how to prevent webrtc leaks outside the socks tunnel except with the firefox socks settings and have the DNS set by the socks5 (VPN on the phone). Though it shouldn't be too hard. Just some modification of the DNS in the network settings

@softmoth
Copy link
Author

Thanks for replying with your solution! I'm glad you found it.

@gmn42
Copy link

gmn42 commented May 14, 2021

Thanks for the solution, it works great! I've been trying solve exactly this problem for a while, since some applications and devices (esp. streaming players like Chromecast) don't honor proxy settings, even when they have them.

A couple of notes on my implementation:

  1. On the phone, I use ssh (running under termux) with the DynamicForward option as the SOCKS5 server. This is convenient because I can either just connect to a sshd on the phone (unrooted, running on a high port number), or I can connect to an outside SSH server and get a easy VPN, while still getting the benefit of using the phone's untethered IP address and without having to root the phone. (Note that this may not be terribly secure because DNS and UDP aren't tunneled, but it gets around geoblocks).

  2. On the OpenWRT router, I just put the iptables rules in /etc/firewall.user (which can be accessed via the LuCI Firewall - Custom Rules page) and used the stock init that came with the openwrt package. Your init script is better because it cleans up after itself on shutdown, though.

I'll check out Socks Server Ultimate... if it supports UDP forwarding (ssh doesn't), it could be useful. It hasn't been a big problem so far because the (streaming) apps I'm using fall back to TCP and I'm not trying to game or anything where the latency would really be an issue.

@softmoth
Copy link
Author

I'm glad to hear it. It is good to have a few options documented.

@animer3009
Copy link

animer3009 commented Mar 17, 2022

Script is causing iptables loop.
can you solve this?

darkk/redsocks#108

@softmoth
Copy link
Author

I'm sorry, I haven't used this for a while and don't have the hardware set up anymore. If anyone debugs it and has a fix suggestion I will update the gist, but can't do troubleshooting myself at this point.

@animer3009
Copy link

@softmoth can you give direction, how to send UDP traffic over proxy?

@softmoth
Copy link
Author

softmoth commented Jun 2, 2022

I didn't get that working, I just used DNS over HTTPS and avoided UDP where possible. Not ideal, but it was OK for me.

@animer3009
Copy link

I didn't get that working, I just used DNS over HTTPS and avoided UDP where possible. Not ideal, but it was OK for me.

Sorry, can you explain more about DNS over HTTPS? Why do we need it in this case and how to set it up?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment