how to get around public network filters

sometimes you get on public wi-fi and it turns out it restricts the ways you can use the network just to be annoying. this is an informal set of resources for getting around that. this glosses over a bunch of underlying networking concepts but i could make a separate post explaining that if needed

mac address based filtering

this is common with networks that offer a time-restricted "free trial" before presenting a paywall for continued access. 99% of the time the filtering is done by the device mac address, because there really isn't a better way to fingerprint individual devices that aren't otherwise authenticated in any way. so the solution is easy, just change your mac address and then the network will think you're a different device

android: if you're rooted and especially if you run a custom OS, ifconfig might be able to change your mac address. it works on my LOS phone at least

ifconfig wlan0 down
ifconfig wlan0 hw ether 00:11:22:33:44:55
ifconfig wlan0 up

linux: NetworkManager allows changing the mac address using the "cloned mac address" option. you can even script it with nmcli to shuffle addresses and reconnect every free trial period. otherwise, try macchanger

iphone, mac, windows: i'm not entirely sure that you can. never tried

DNS-based filtering

sometimes networks restrict which sites you can access by simply redirecting DNS lookups made to the router resolver to a filterwall page. you can detect this by comparing a DNS lookup for a filtered site to the known real IP for that site (you can get this using an online DNS lookup page, as a last resort). for example

$ dig +short blockedsite.horse

if this sort of DNS tampering is in use, you can try the same lookup against a working external DNS server. OpenNIC has a cool set of DNS servers you can use (bonus points: you get access to cool hacker TLDs like .cyb and .pirate)

$ dig +short blockedsite.horse @192.34.59.80

if something like this works, change your system DNS servers. for NetworkManager you should go to the IPv4 section, change the type to DHCP addresses only and add DNS servers in the field, then reconnect to the network. also do the same for IPv6 if you have IPv6. on android you're required to use static addressing if you want to set custom DNS servers, or you can use this workaround app on f-droid. on windows you do control.exe ncpa.cpl and then a bunch of clicking i can't be bothered to actually remember because of course microsoft makes this as difficult as absolutely possible

or as a general rule you could just never use any DHCP-advertised DNS servers ever. for eg personal laptops and phones you use everywhere it doesn't really make sense to do that anyway unless the network blocks external DNS servers

IP-based filtering

smarter networks filter by actually redirecting IP packets and there isn't really a good way to get around this other than to tunnel through somewhere else. if you set up an openvpn or wireguard endpoint and you're able to access it then routing everything through there will effectively avoid the local network completely. but it depends on the network actually allowing your server and the VPN ports, which it might not

more locked down networks

sometimes networks like to do stuff like block every port except 53, 80, and 443 because they're fun like that. in this case, you can try running a VPN endpoint on TCP port 443, which is obviously an "https server". as long as your server's IP isn't filtered, you should be able to get to it

there are a lot of guides on the internet for setting up openvpn or wireguard servers, i recommend doing it. you could also use an existing commercial VPN service if you want. some even offer TCP/443 endpoints, which is handy. but commercial services are more likely to be IP-blocked as well

tor

you can also use tor with bridges, particularly ones that run a pluggable transport to try to evade blocking. the main issue with tor is because it's so well known it's more likely that locked down networks are going to have specific measures to block it. but it would otherwise be a good option

really locked down networks

if the network tries to do something like deep packet inspection or tries to MITM the TLS connections on port 443 with its own certificate that it forces you to install and inspects the plaintext inside then you're a little more hosed, because openvpn on port 443 would be easily caught. i had an idea for this case, which is to create a real HTTPS server that runs a websocket endpoint and run the VPN link through that with additional encryption for the websocket data, which would likely pass even very strict TLS-stripping and protocol inspection
getting even more esoteric, if there's a stricter filter list that blocks access to servers you can control, then you could theoretically create a tunnel over existing public services that would likely be explicitly allowed by the network, like google mail or face book messenger or something, though you run the risk of those services getting angery with you

i'm not really aware of any public tools for this sort of thing. it hasn't happened enough times for there to be a need for me personally but i feel like tools might be helpful to have

extremely locked down networks

this is the case where a network immediately presents you with a paywall, or otherwise directly blocks access to everything and there's no way to get out

except there is actually a way to get out, the router's local DNS resolver. because DNS is required to be distributed, the router will access literally any server you want for you if it's necessary to complete a DNS lookup. this ends up being basically the most powerful filter bypass at the cost of being very slow especially if, for example, you are on a very high latency satellite uplink

the tool for this is called iodine, located here: https://github.com/yarrick/iodine
there's also an android client: https://f-droid.org/en/packages/org.xapek.andiodine/

first, get a short domain name, as short as possible because the uplink is based on how many chars fit into the subdomain (out of the 255-char max for DNS - sometimes even lower for certain networks). set it up with NS records that point to a server you control, and run the iodine server on there

you can test the setup by trying to resolve any subdomain of your domain that starts with z, and you should get a response if it's working

to connect, run the iodine client then add default routes for the tun device it creates. optionally, set up iptables rules to drop traffic to everything other than important services you want to access as a way to reduce traffic because iodine can get pretty slow depending on the resolver it's going through. i have this script

#!/bin/bash

# run with sudo, or be fancy and run with CAP_NET_ADMIN and CAP_NET_RAW and CAP_NET_BIND_SERVICE

SERVER= # server domain
PASSWORD= # iodine password you started it with (you should have a password)
SERVER_IP= # ip of the server when accessed through the tunnel
DEV_INET= # the device name you get internet through, eg wlan0
DEV_DNS=dns0
OPTS="" # set options if you know the right parameters for the current network, otherwise iodine will auto-detect them

set -m
echo Using opts $OPTS
echo "Setting up iptables"
route=$(ip route show dev $DEV_INET | grep default | cut -d' ' -f2-)
echo "Found default route $route"
for resolver in $(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'); do
    echo "Found resolver $resolver"
    sudo ip route add "$resolver" $route
done
(sleep 10;
    echo Adding routes;
    for i in {1..5}; do
        if ip route add default via $SERVER_IP dev $DEV_DNS metric 50; then
            break;
        fi;
        echo routes failed;
        sleep 1;
    done) &
iodine -P $PASSWORD -r -f $OPTS $SERVER

a better iodine

right now iodine sucks because it tries to transparently wrap all of IP, which is fine but the overhead from IP and TCP headers is a lot, and it could be making better use of that bandwidth. a better iodine might also support a SOCKS-proxy-like mode with a more stateful server, where instead of passing raw IP frames the client can use special control messages to instruct the server to open and close TCP connections on its behalf, and to transmit or receive data on a previously referenced connection, which would avoid a lot of the header overhead. UDP could use a similar optimized protocol

also, an iodine PT for tor would be really cool and someone should make one

addendum: intra-LAN filtering

this is a slightly unconventional case with an unconventional solution but sometimes you end up on a hardwired network you don't control where because the people who set up the network had interesting ideas about security, you can't access other devices on the LAN, only the internet. for example (this is just an example, nothing related to reality) in a uni dorm environment. but it also turns out that the LAN filtering is done at layer 3 while your devices are connected to the same underlying switch, and therefore can exchange layer 2 messages that are not IP. so instead of just like, running my own ethernet cable between the devices i made a program that converts IP into IP except the ethertype is different so it's definitely not IP(tm) and it turns out this actually works and bypasses the filter!
anyway i highly doubt this will be useful to literally anyone else but here's the (2 year old) codebase for this https://git.lain.faith/haskal/h804tun