Repairing YouTube at the router level

:(

🙁

Greetings to all. Literally on August 1st, right in the night, YouTube started lagging terribly. Naturally, I didn't like it very much. Well, let's figure out why and how to fix it in the conditions of my personal network.

What's happened?
What happened is well described here on Habr – https://habr.com/ru/articles/832678/
In short, in my own words – during the SSL connection setup, the domain we are connecting to is transmitted in the open (the so-called SNI). And if it is googlevideo.com, then “interesting things” start happening. You can check this locally using the commands in the article.

$ curl https://speedtest.selectel.ru/100MB -o/dev/null

In my laptop terminal

In my laptop terminal

As you can see, the download speed is quite decent. Now let's try to connect to the same server, but passing another domain during the handshake.

$ curl --connect-to ::speedtest.selectel.ru https://manifest.googlevideo.com/100MB -k -o/dev/null

In my laptop terminal

In my laptop terminal

That's it, we've arrived…

What to do?
It is obvious that we are being cut by domain using DPI. There are already quite well-known projects, such as Goodbye DPI. But it is for Windows, which I don't have at home, and it requires installation on a single computer and does not allow me to cure my entire home network. Thanks to the author, right in the readme he has collected a list of projects that do similar tricks for other operating systems. The whole point of these projects is to somehow distort the domain string transmitted in the open. If it is very simple, then in the case of open HTTP it is easy to change the Host header, for example, like this:

Host: googlevideo.com
hoSt:googlevideo.com # поменян регистр и убран пробел

And those strange things that do wonderful things will not be able to correctly analyze the traffic and do something. In the case of a TLS connection, as I understand it, they simply take a TLS packet and split it into several TCP ones, so that parts of the string with the domain are in different TCP packets. And at the same time they change the order of TCP packets, first the end, then the beginning is sent. The TCP protocol itself allows this and everything will work correctly on the end server. But the wonderful hardware is too stupid and their authors clearly did not read the spec. Here is such a nice competition.

As a reminder, I wanted to cure my entire home network, and to do this, I needed to do it directly on the router. My router is a Zyxel Keenetic Giga III, which is probably ten years old… Keentic has already become a separate brand without Zyxel, and my router has been working like a clock all this time. I started thinking about upgrading and buying a router that could run OpenWrt. The manual below is valid for any router under Linux that has iptables and init.d.

After reading a bit, what was my surprise that on a rather closed Zyxel you can install a set of Linux binaries and the OPKG package manager from OpenWrt. The router was quite expensive, it was worth the money I paid for it, after so many years it was able to surprise me. A couple of paragraphs further – you can skip if you do not have Keentic. Now we will launch OPKG on my router. In general, there is the whole manual from the manufacturer how to do it. I will describe it very briefly.

First you will need to go to the web interface and deliver all OPKG components.

Router UI where we deliver native firmware components

Router UI where we deliver native firmware components

As usual, such devices have a tiny amount of internal memory, hardly enough for flashing. No problem. Take a USB flash drive, format it in EXT4. Create an install directory in the root and put a set of binaries from the official site (more precisely, from the link to the entware project from the official documentation). In my case, for the mipsel platform – https://bin.entware.net/mipselsf-k3.4/installer/EN_mipsel-installer.tar.gz After browsing https://bin.entware.net/ you can find a similar installer for ARM or mips on bigendian, if you have some kind of tricky keenetic. Next, we plug the flash drive into the router, if everything is fine, the router itself will unpack and delete the archive. And we will be able to connect via ssh to port 222.

By the way, if you make a mistake in the platform, it is better to just go to the router's ssh on port 22 and try in the console exec sh .

If it's not the right platform, the error will be clearly visible. I didn't immediately understand what processor I had, I had to sort it out.

If the file exists and is not for the platform, then exec format error. If the file does not exist, then it clearly says that it does not exist.

If the file exists and is not for the platform, then exec format error. If the file does not exist, then it clearly says that it does not exist.

The password for logging in via ssh on 22 is the same as the web interface. On 222, the login password is root/keenetic. After the first login, don't forget to do passwd and change the password. If everything worked out, then either via ssh connection to port 222, or via exec sh We finally get almost full-fledged Linux on Zyuxel. Hooray! And a huge thank you to the manufacturer for this feature.

And here we are on the router, in Linux

And here we are on the router, in Linux

Well, now the part common to routers with OpenWrt or similar Linux. All we have left to do is install software that will twist and turn and want to deceive TCP packets and turn all traffic to this software. There is a lot of such software. To begin with, let's immediately install what we may need, in my case:

# opkg install ipset curl gzip grep git-http gcc make cmake

If you have little space – you can install nothing. You can throw the binary via scp and that's it.

Now I started choosing a project to launch. I liked it quite a bit. this. Simply because it was assembled from raw materials right on the router, launched and worked. But, unfortunately, it only provides a SOCKS proxy and I have no desire to configure each device in the home network. Let's go further, a project was found prohibit. It looks very cool, but its automatic installation scripts started to write too many errors, more than I am ready to understand and the project will be delivered normally. And the script code is also complicated. Oh well, a quick reading of the readme told me that there is a binary that does everything that is needed, it even lies assembled right in the repo for different platforms. That's what I need. And the scripts, okay, I'll do everything myself without them. So, here's what I need:

# mkdir git
# cd git
# git clone https://github.com/bol-van/zapret.git
# cd zapret
# ./install_bin.sh
# cd /opt/etc/init.d/
# vi S51tpws

And then insert the service code that I wrote.

#!/bin/sh

SCRIPT=/opt/root/git/zapret/tpws/tpws
PIDFILE=/var/run/tpws.pid
ARGS="--daemon --bind-addr 192.168.0.1 --port 999 --disorder --tlsrec=sni --split-pos=2 --pidfile $PIDFILE"


start() {
  if [ -f $PIDFILE ] && kill -0 $(cat $PIDFILE); then
    echo 'Service TPWS is already running' >&2
    return 1
  fi
  $SCRIPT $ARGS
  iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j REDIRECT --to-port 999
  iptables -t nat -A PREROUTING -i br0 -p tcp --dport 443 -j REDIRECT --to-port 999
  echo 'Started TPWS service'
}

stop() {
  if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
    echo 'Service TPWS is not running' >&2
    return 1
  fi
  echo 'Stopping TPWS service...'
  kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
  iptables -t nat -D PREROUTING -i br0 -p tcp --dport 80 -j REDIRECT --to-port 999
  iptables -t nat -D PREROUTING -i br0 -p tcp --dport 443 -j REDIRECT --to-port 999
}

status() {
  if [ -f $PIDFILE ] && kill -0 $(cat $PIDFILE); then
    echo 'Service TPWS is running'
  else
    echo 'Service TPWS is stopped'
  fi
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
esac

Further

# /opt/etc/init.d/S51tpws start

We measure

On my laptop, after starting the service on the router

On my laptop, after starting the service on the router

We try YouTube manually and see with our own eyes that it has started working very, very fast.

A little clarification. The code above uses only one binary from the zapret project – tpws . It has a transparent proxy interface that distorts packets by deceiving DPI. This binary has a bunch of flags for starting. In the init.d service code, I specified the arguments for starting that work for me. You can remove –daemon and just start it in the terminal, playing with the parameters. Don't forget to register routes to your service in iptables before rotating it manually. In my case, routes are added and deleted directly in the service code.

Specific. init.d on Zyuxel for some reason is in /opt/etc. On bare OpenWrt most likely in the root /etc. The prefix S51 of the service file S51tpws is taken from somewhere in the guts of entware, without this prefix the service does not start itself at startup. Again, in bare OpenWrt most likely it is not needed. br0 is the name of the local network interface, on it the IP of my router is 192.168.0.1. So that the tpws service listens only on this interface (and not on the external one as well), I also registered it among the arguments for starting the service.

That's it, that's all. Now all traffic going to external ports 80 and 443 from my network is processed and distorted by the tpws service. I think it's no secret if I say that YouTube will most likely be completely banned in the foreseeable future. Based on this, this solution is temporary. Or, perhaps, in the future there will be another binary that will send all traffic via ICMP to my private virtual machine somewhere in the Netherlands… The main thing is the beginning, and I really like this design on a home router. Thank you all if you read to the end.

ps I give full consent to reprint this article in any sources. I declare it public domain. Do what you want, but it is better to improve and develop 🙂

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *