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 VPSReverse 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