Running a webserver on Android (crimes against computing) (No root? No problem)
Background
I have been running GrapheneOS for the last ~4 years. Before doubling down on my anti-malware, anti-spyware, voluntary-social-pariah lifestyle, I used to run stock google roms. I briefly attempted to flash LineageOS on a OnePlus phone but there was a mismatch in the hardware/software so I effectively bricked the device.
On these degoogled roms (if you choose to actually degoogle Lineage entirely), resorting to the google play store requires entirely defeating the purpose of flashing a rom that increases freedom, privacy, and security. Instead, we have a few options.
The solution to the “no apps”? Download apks. The solution to “no updates”? Download a glorified APK manager.
- f-droid, the cream of the crop
- accrescent, a novel apk repo for grapheneos
- Obtainium, pulls apks from git* repos
f-droid has been my primary way of installing software on android for nearly 10 years at this point. F-droid is mostly FOSS and adds a warning message to software that might violate freedoms or privacy.
After knowing about the existence of termux for a long time, I decided to look at the packages available. Much to my surprise, typical UNIX daemons are packaged and supported on termux (ie httpd, sshd, etc).
Enter termux
Termux is a terminal emulator for android. It includes a minimal base system and the apt package manager for managing packages. Coming from real linux with real root, the Termux environment is only slightly uncomfortable. No root is required to run Termux. Termux leverages the underlying linux system and a series of clever prefix tricks.
Termux does not abide by standard UNIX filesystem hierarchy standards. Termux stores it’s “root” filesystem as application data. Termux is single user. Termux is NOT linux. If you want a more linuxy environment, consider Installing a full linux distribution under a proot. Bind mounts are powerful.
The various termux extension apks are all available in f-droid. Install the Termux
and Termux:Boot
. The first is the core program, the latter two make it possible to run termux at boot time and allow termux to prevent android from sleeping. If you intend to run this on your actual phone, probably avoid the Termux:API
package because it would allow anyone who cracks ssh to access the underlying android system and possibly obtain sensitive information.
Make it suck less
In my daily life, I don’t use termux because touchscreen keyboards are all but entirely unusable. The first thing to do is set up ssh so I can mitigate frustrations and rage.
~ $ pkg install openssh
~ $ passwd
New Password:
Retype Password:
New password was successfully set
~ $ sshd
~ $ ifconfig
Now I can ssh to the phone.
main@t490:~$ ssh 192.168.1.17 -p 8022
main@192.168.1.17's password:
Welcome to Termux!
Docs: https://termux.dev/docs
Donate: https://termux.dev/donate
Community: https://termux.dev/community
Working with packages:
- Search: pkg search <query>
- Install: pkg install <package>
- Upgrade: pkg upgrade
Subscribing to additional repositories:
- Root: pkg install root-repo
- X11: pkg install x11-repo
For fixing any repository issues,
try 'termux-change-repo' command.
Report issues at https://termux.dev/issues
~ $
Setting up remote access is documented on the termux wiki
Setting up services
Apparently termux needs a restart before you can enable/disable services
~ $ pkg install termux-services
~ $ ls $PREFIX/var/service
~ $ exit
~ $ sv-enable sshd
~ $ sv up sshd
I then restart termux again to verify that the services actually autostart. It did. The next thing I will do is enable termux to start when the phone boots.
The wiki contains information about services under termux
Termux on boot
Install the Termux:Boot
apk, click it once, go to android’s app settings and disable battery optimizations for Termux
and Termux:Boot
. Add a file to instruct termux what to do on boot.
Instead of running termux-services, however, I will be manually starting programs. Less complexity is better in my opinion.
~ $ pkg add vim
~ $ mkdir -p ~/.termux/boot
~ $ vim ~/.termux/boot/start
~ $ cat ~/.termux/boot/start
#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
sshd
~ $ chmod +x ~/.termux/boot/start
Reboot the phone to verify that everything actually starts at boot time. You may or may not need to look in the android wifi settings to find the device’s IP.
Installing a webserver, php
install, edit the server’s config to enable PHP
~ $ pkg install apache2 php-apache php neofetch
~ $ ls $PREFIX/libexec/apache2 | grep php
libphp.so
~ $ echo "LoadModule php_module $PREFIX/libexec/apache2/libphp.so" >> $PREFIX/etc/apache2/httpd.conf
~ $ echo -e "<FilesMatch \.php$>\n\tSetHandler application/x-httpd-php\n</filesMatch>" >> $PREFIX/etc/apache2/httpd.conf
~ $ sed -i 's/DirectoryIndex index.html/DirectoryIndex index.php/g' $PREFIX/etc/apache2/httpd.conf
~ $ sed -i 's/^LoadModule mpm_worker_module/#LoadModule mpm_worker_module/g' $PREFIX/etc/apache2/httpd.conf
~ $ sed -i 's/^#LoadModule mpm_prefork_module/LoadModule mpm_prefork_module/g' $PREFIX/etc/apache2/httpd.conf
Add a fun index.php
~ $ pkg install neofetch aha
$PREFIX/share/apache2/default-site/htdocs/index.php
looks like:
<!DOCTYPE html>
<head>
<style>
body{
background-color: #1e1e1e;
color: #ffffff;
}
</style>
</head>
<body>
<?php
$fetch = system(" sh -c \" neofetch | aha \"");
printf("<pre><code>%s</code></pre>", $fetch);
?>
</body>
</html>
Enable httpd at boot time
~ $ echo "apachectl start" >> ~/.termux/boot/start
Analysis
Why would you want to ever do this? I'm not entirely sure. Maybe smartphone based servers is the epitome of commodity computing (or commodity computing taken to absurd limits). Charging a lithium battery until the end of time will destroy it. Considering the existence of cell phone based click farms, this type of setup is not entirely impossible if you can get a cheap/used phones.
The most important thing I realized during this project is that APKs can open random ports! You must remember this when installing nonfree apps where the only way to tell if the program is listening on a port on a non-loopback interface is to babysit it with a traffic sniffer like wireshark. Double NAT and router firewalls make this more difficult but it's still not impossible. Is your router UPnP enabled? Have you considered that an attacker can use any of the available technologies we ourselves use to punch through NAT?
Yet another thing I considered during this project is that android has the ability to run a JIT compiler upon app launch. Where do the sources come from? The app developer's domain. Think about domain hijacking and if it's even worth using an app that downloads sources to do JIT compilation? All it would take is a single domain hijacking and your phone is now pwnd, webshell and all.
My trust for android is still relatively high When using free and degoogled roms with free and degoogled apps but I trust it less than a proper Linux distribution. My trust for googled android is at the same level as my trust for windows - "why are you still using this? It's malware by any other name." In response to "just buy iphone bro!! iphone most secure! What, are you poor?" -- I would rather live dangerously free than buy into a company that actively engages in anti consumer practices, makes it difficult or impossible to run your own software on your own hardware that you purchased outright in cash, and is still equally if not more vulnerable than a standard stock android phone (as evidenced by zerodium paying more for certain android exploits than equivalent ios exploits).
I will be nuking the termux installation immediately. I am going outside. I am going for a walk. I need to think about the implications of putting our entire lives on ubiquitous glass slabs that are hackable with minimum effort. Everything you think you are can be pwnd in a moment of carelessness.