English (unofficial) translations of posts at kexue.fm
Source

Tinkering with HiWiFi on New Year's Eve: SSH Reverse Proxy

Translated by DeepSeek V4 Pro. Translations can be inaccurate, please refer to the original post for important stuff.

Happy Year of the Monkey!

Today is New Year’s Eve. I would like to simply wish everyone a Happy New Year’s Eve and a Happy New Year! May everyone be promoted to "learning gods" (academic superstars) in the coming year. ^_^

Over the past two days, I have mainly been tinkering with the router at home. Usually, only my parents are at home, so to save money, the house connects to the internet by relaying the neighbor’s network. Originally, we used a Xiaomi Mi Router Mini, but its functionality is extremely limited in relay mode. I didn’t want to flash third-party firmware (because that would lose the app control features, which is inconvenient), so I simply switched to a HiWiFi 3. HiWiFi retains most of its functions even in relay mode (I think this is how it should be; I don’t understand the logic of why the Xiaomi Mini loses so many functions after relaying).

As a tinkerer, when a new router arrives, there are always many things to configure. HiWiFi itself is based on OpenWrt, so it has high playability. First, I completed the relay and got online, which is very simple and won’t be detailed here. Second, I needed to obtain SSH permissions, which HiWiFi calls "Applying for Developer Mode," or Root (it feels like HiWiFi wants to be the Apple of the router world, but in this day and age, that kind of development model is likely difficult to sustain). This step isn’t hard either, but applying for it voids the HiWiFi warranty (I don’t understand the logic behind this either).

This article mainly introduces how to install Python on OpenWrt (HiWiFi) and establish an SSH reverse proxy (to achieve intranet penetration).

Installing Python to SD Card

Once you have SSH permissions, you can do many things. The first thing to do is install Python, which enables a wide range of possibilities. This took a bit of effort. First, you need to modify the OpenWrt software sources by editing the following three files:

/etc/opkg.conf
/etc/opkg.d/opkg-secure.conf
/etc/opkg.d/opkg-fast.conf

Comment out the first line:

# src/gz barrier_breaker https://upgrade.hiwifi.com/upgrade_file/ralink-HC5861/0.9017.1.11380s/packages

Then add the following at the bottom:

src/gz barrier_breaker http://downloads.openwrt.org.cn/PandoraBox/ralink/mt7620_old/packages/

After deleting the cache files, you can update the sources and install software:

rm /var/opkg-lists/barrier_breaker
opkg update

Note that the remaining space in the HiWiFi 3 ROM is limited, so it is best to install Python onto the SD card. To do this, first check the mount point of the SD card using df -h (mine is /tmp/storage/mmcblk0p2). Then, modify the same three files again:

/etc/opkg.conf
/etc/opkg.d/opkg-secure.conf
/etc/opkg.d/opkg-fast.conf

Below the line:

dest root /

Add:

dest usb /tmp/storage/mmcblk0p2

Additionally, you need to modify the system environment variables by editing /etc/profile (pay attention to the parts in red):

export PATH=(*\textcolor{red}{/tmp/storage/mmcblk0p2/usr/bin:/tmp/storage/mmcblk0p2/usr/sbin:}*) /bin:/sbin:/usr/bin:/usr/sbin:$HIWIFI_CRYPTDA
export LD_LIBRARY_PATH=(*\textcolor{red}{/tmp/storage/mmcblk0p2/lib:/tmp/storage/mmcblk0p2/usr/lib:}*) $HIWIFI_CRYPTDATA/lib:$HIWIFI_CRYPTDATA

Now, you can use the following command to install Python to the SD card:

opkg install python -d usb

Then install setuptools to get easy_install, followed by pip and the requests library. At this point, my Python environment configuration is complete.

Configuring SSH Reverse Proxy

Next, I wanted to find a way to penetrate the intranet so that I could manage the home router from school. There are many methods for this, such as ngrok (I haven’t tried it, but looking at tutorials, the configuration seems a bit troublesome), n2n (this is based on P2P, which I like, and it works on OpenWrt; I configured it successfully on my school router, but it failed on the HiWiFi, so I gave up), and the PeanutHull (Oray) Intranet Edition (HiWiFi has a PeanutHull plugin, which is okay, but the free version has too many restrictions). Since I wasn’t satisfied with the first three, I had to use an SSH reverse proxy.

The principle of an SSH reverse proxy is the inverse use of SSH, which is exactly the opposite of our normal SSH login sequence:

Normal SSH:
My Computer \to Intranet Router \to My VPS

Reverse Proxy:
My Computer \to Your VPS \to Intranet Router

Implementation is very simple—just one line of code—and it works on almost all platforms (as long as they support SSH). Of course, the preparation work is significant.

To use an SSH reverse proxy, you need your own VPS with a public IP. I use an Alibaba Cloud server, which costs 9.9 RMB/month for students, very affordable. First, configure the VPS by modifying /etc/ssh/sshd_config to include:

GatewayPorts yes

Then restart SSH with /etc/init.d/ssh restart. Next, on the HiWiFi OpenWrt, establish the reverse tunnel to the VPS using the following code:

ssh -Nfg -R 11111:192.168.199.1:1022 root@1.1.1.1

This is the same as a normal SSH login, where 1.1.1.1 is the public IP of the VPS, 192.168.199.1 is the management IP of the HiWiFi, and 1022 is the SSH port of the HiWiFi (since I only want to SSH into the router). After a successful login, accessing 1.1.1.1:11111 from anywhere is equivalent to accessing the router’s 192.168.199.1:1022. For example, you can run ssh root@1.1.1.1 -p 11111 to see if you can log into the router. (You can also use netstat -nlp | grep sshd on the VPS to check if the port proxy was established successfully.) The meaning of the parameters above can be checked via ssh -h.

At this point, the problem is basically solved, but there are a few issues. First, SSH requires manual password entry interactively. To achieve password-less login, you need to generate a key locally and upload it to the VPS (i.e., the private-public key mechanism). The specific steps are to first generate the public key using the following code (this is the built-in method on OpenWrt; general Linux systems should use ssh-keygen):

dropbearkey -t rsa -f /etc/dropbear/id_rsa
dropbearkey -y -f /etc/dropbear/id_rsa | grep ssh-rsa > /tmp/id_rsa.pub

Then add the content of /tmp/id_rsa.pub to the VPS server’s ~/.ssh/authorized_keys (create it if it doesn’t exist). Then, log in using:

ssh -i /etc/dropbear/id_rsa -Nfg -R 11111:192.168.199.1:1022 root@1.1.1.1

You will find that you no longer need to enter a password.

Second, SSH itself is not very stable; if there is no response for a long time, it will automatically disconnect. One way to solve this is to use autossh (opkg install autossh -d usb) instead of the built-in SSH. It is an SSH client with monitoring capabilities. The autossh code is similar:

autossh -i /etc/dropbear/id_rsa -M 11112 -Nfg -R 11111:192.168.199.1:1022 1.1.1.1

Its principle is to add a port 11112 to monitor the connectivity status of port 11111. If it disconnects, it automatically reconnects.

Third, how to start with the router. The router could restart at any time due to a power outage, so the command needs to be added to the startup items. This is also simple: just add it to /etc/rc.local. However, there are two small issues: (1) My router accesses the internet via relay. It is very likely that when this script runs, the network has not yet connected. Connecting to SSH without internet is meaningless, so I need to check if the network is connected before executing (of course, you could use sleep to wait long enough, but that isn’t very reliable). My method for checking network connectivity is simple: I created a test.html file on my website with only the string "pass". If I can access this page and get "pass", the network is connected. (2) If a tunnel was successfully established previously and the router restarts, the corresponding tunnel might still be cached on the VPS. In this case, running the code again will default to using the cached tunnel and show success, but ssh root@1.1.1.1 -p 11111 will fail (this action clears the VPS cache). Therefore, after establishing the SSH tunnel, a trial use is needed to check if it is available; if not, it must be re-established. Since SSH itself runs as a blocking process, we can utilize this.

The code is as follows:

#!/bin/sh

local_ip=`ifconfig br-lan|grep 'inet addr'|awk '{print $2}'|awk -F: '{print $2}'`
vps_ip=1.1.1.1

while true
do
 wget http://kexue.fm/test.html
 a=`cat test.html`
 rm test.html
 if [ "$a" = 'pass' ]
    then
        autossh -i /etc/dropbear/id_rsa -M 11112 -Nfg -R 11111:$local_ip:1022 $vps_ip
        ssh -i /etc/dropbear/id_rsa -N $vps_ip -p 11111
    fi
    sleep 10
done

This integrates LAN IP detection, network connectivity detection, availability detection, and automatic reconnection. Save this code as run.sh in the root directory, run chmod +x run.sh to grant execution rights, and then add the following before exit 0 in /etc/rc.local:

source /etc/profile
/run.sh

The first line is very important because my autossh and other tools are installed on the SD card; the system variables must be loaded for them to work properly. When this script runs, the system variables might not be fully loaded, so it is best to import them manually to ensure normal operation.

Finally, everything is set up. For convenience, I also bound one of my subdomains to the VPS. Thus, I have built a relatively perfect intranet penetration platform, which basically outperforms the PeanutHull Intranet Edition.

References

When reposting, please include the original article address: https://kexue.fm/archives/3604

For more detailed reposting matters, please refer to: Scientific Space FAQ