Heya! So, lately I’ve been thinking about how the current state of media directs us to spending a lot of time focusing on global events and people. We are so connected with the entire world, that sometimes we lose sight of what is happening right outside our windows. Instead of trying to reach the largest audience possible by sharing events and ideas on social media, what if we steered our efforts towards our local communities? This could look like pinning up event posters outside, gathering for mutual aid community dinners, oor hosting a web page on an open local network…??
I had seen this idea in Berlin — Google was attempting to open a new headquarters in Neukölln and the people were not going to allow it. Alongside the protests, someone had setup a local network where Google was planning to build its office. When you connected to the network, it would pop up a page of anti-google propaganda that everyone should be aware of. It was a cool supplementary way to share information, localized to a specific area and idea.
I wanted to implement something like this here in NYC, and maybe take it a step further by including a local network chat to spark the sense of community along with some (abolitionist?) propaganda. I came up with a list of the most important features…
- The page should pop up automatically after you connect (Captive Portal).
- The local network should not need internet connection.
- The router should be able to run a small server for the chat API.
- All processes should survive a reboot.
Lets do iittt::::
We need a portable router for this project. This could come in many different forms, I even contemplated using my Raspberry Pi, but eventually settled on the GL.iNet Slate Router for it’s simplicity and specialized functionality.
This cute portable router comes with an installation of
OpenWRT, as well as a Admin Panel web interface. I knooww we all want to be terminal purists sometimes, but this admin panel is actually really nice and helpful to get a visual representation of the router state.
To prep for this experiment, I used the Admin Panel to set up an open guest network named
Starbucks WiFi…(ask me about it :p) I also enabled a captive portal for the guest network using the interface. Depending on which router you use, you may have to figure out some of those things with commands, but I have been blessed with this interface and will enjoy its benefits:)
Setting up the Captive Portal
Now that the captive portal has been enabled, when connecting to the router, I receive a popup html page! Now to swap it out with our own.
OpenWRT comes with the
NoDogSplash captive portal manager. Looking through the docs, I found that the html page that it sends to newly connected users is located in
So all we need to do is copy over our html page with (anti-capitalist?) propaganda using scp from our computer.
scp index.html firstname.lastname@example.org:/etc/nodogsplash/htdocs/splash.html
Wonderful! Now every time you connect to the open guest network, it should bring you to your (anti-google?) propaganda page.
Allowing Captive Portal to Work Offline
NoDogSplash captive portals will not work without internet. If the router fails to resolve the
DNS request for the operating systems “connectivity check” URL (mac uses
NoDogSplash will return an error and deem the network/captive portal unusable.
I found this to be quite a blocking problem, since one of my goals was to take my local network chat to places where a WiFi connection was not guaranteed (NYC Metro, street protests, etc). Furthermore, since all data for the chat is local to the router, there really was no reason it needed WiFi..
After scrolling through some Github issues, I found a hack to basically configure
NoDogSplash to resolve all
DNS queries locally with the same random public address, making them seem to pass the “connectivity check” and allow
NoDogSplash to continue.
(on router)uci add_list dhcp.@dnsmasq.address=’/#/126.96.36.199'# saves the config edit for persistency after reboot
uci commit dhcp service dnsmasq restart
Setting up the Chat Server
At this point, we basically have enough to recreate the Berlin anti google setup:) However I still wanted to see if it was possible to setup a simple chat server. The simplest chat ever needs a running server with one route for posting a message, one route for getting all messages, a super sophisticated .json file database, and an html page to display the chat.
The router model I have only has 128 mb of RAM.. so I thought about downloading
Python-Light, but it was too light and did not have
SimpleHttpServer. I decided to just pray and hope the device could withstand the vanilla
First I installed
Python on the router using the
OpenWRT package manager.
opkg install python
Then copied over my server code and new chat html page from my computer ( I wont go into describing how the chat code works here, but its pretty simple and you can check it out here if you want :)
scp server.py email@example.com:/root/scp chat.html firstname.lastname@example.org:/etc/nodogsplash/htdocs/splash.html
Create an empty “database” on the router to store our messages:
echo "" >> /root/data.json
And run the server!
All is well…. but if we open our chat now we can see that requests to the
Python server are failing with a connection time out, meaning that the port our server is listening on is not accessible from our chat page. If we remember,
NoDogSplash is in charge of the captive portal which blocks most of the ports by default, so we can adjust its settings to allow traffic directed to our server port.
uci add_list nodogsplash.@nodogsplash.users_to_router='allow tcp port 8989'uci commit nodogsplashservice nodogsplash restart
Now, if we run the server again and try connecting to our open network, our chat should pop up as a captive portal, happily GETting/POSTing requests to our local server :)
Survive the Reboot, the Final Boss
If you’ve gotten this far.. you should have a captive portal that automatically pops up with a chat window served by the simple
Python server running on the router.
In order to reach our ideal of robustness, we need to make sure our processes can survive a reboot!
Init Scripts to configure daemons that run on startup, if we make our python server run as a daemon, it should hopefully be able to survive a reboot.
OpenWRT docs give a pretty simple example
Init Script, which we can modify for our purposes :
echo "starting chat server"
(sleep 20; python /root/server.py)&
echo "stopping chat server"
Init scripts use the template
/etc/rc.common, a wrapper that provides its main and default functionality, such as
disable. We need to override the default
stop functions. If you want to learn more about the details of init scripts, check out the OpenWRT docs on the subject, they are awesome.
If you noticed in the script, our start function has a lot going on in the line :
(sleep 20; python /root/server.py)&
First off, the process is running in the background — indicated by the
&. I noticed that if I tried running the process in the foreground, the Admin Panel wouldn’t show up! I have a hunch that
init.d start functions are blocking, so whatever you need to start needs to account for that by running itself as a background process.
Another mystery is that if I just ran
(python /root/server.py)& without the
sleep bit, the server would not start up properly. After killing the process and starting it again manually using
/etc/init.d/chat start, everything would work fine! My hunch here is that something needed for python servers to initialize is not available at boot time… would love if someone has more information on that. For now, the sleep timer works :)
We can copy this file from our computer into the designated directory of init scripts:
scp chat.sh email@example.com:/etc/init.d/
And enable it! Enabling the process allows it to startup on boot.
sudo chmod +x /etc/init.d/chat.sh
Nowwww cross your fingers and lets reboot!!! To make sure your python server is running in the background after the reboot, you can run
ps | grep python
and check if the server process survived :)
We made it! This article may not accurately portray the amount of mental breakdowns that occurred during this exploration, but hey thats linux so it’s implied :) I hope after an adequate amount of flipped tables you are able to get this to work too and we can spread the joy of LAN chats & local environment awareness :P
check out my other things @