tl;dr I’m Too Lazy to Read, give me the one liner at the end.
Gogo Inflight Internet Show Me How You Work
On a recent flight I decided to learn a bit how Gogo Inflight Internet WiFi does access control. By connecting to the access point you’re directed to a captive portal requesting payment and it seems unable to access the Internet otherwise. A quick port scan of my remote server show that all ports except 80/tcp
and 3128/tcp
appear blocked.
During my layover, I forwarded port 3128/tcp
to 22/tcp
on my server to see if I could connect to OpenSSH. Surprisingly it worked, and this little hole enabled me to remotely access the server and continue exploration.
The next was to fire up a kylemanna/openvpn server to proxy my data on port 3128/tcp
. That worked as well. However, everyone knows that TCP in TCP tunnels are bad, and by observing ping times on my flight blow up after a single lost packet, it behaves as poorly as expected. No fun, no good, but surely a start.
Check If the Firewall Relays UDP Traffic
A better performing solution uses TCP in UDP tunneling as tunnels are supposed to work. To do that I fired up the same kylemanna/openvpn image on my server with a slightly different configuration. Boom! Everything worked on my laptop and my cell phone through the OpenVPN tunnel. The Internet at your fingertips through an apparent firewall hole.
But how would others do this? Read on my friend.
How to Setup OpenVPN on Port 3128/UDP
Before you get on a flight, setup a remote server like a $5/mo Digital Ocean droplet (Use my promo code to get a $10 credit!) in a region where you’ll be traveling for best performance (i.e. San Francisco vs New York City).
Step 1 – Start A Server With Docker
I recommend selecting the Docker One-Click App from Digital Ocean.
Step 2 – Setup the OpenVPN Server Using Docker
Change SERVER_IP
variable to match your server’s public IP address.
OVPN_DATA="ovpn-data"
SERVER_IP="127.0.0.1"
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://$SERVER_IP:3128
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
docker run -v $OVPN_DATA:/etc/openvpn -d -p 1194:3128/udp --cap-add=NET_ADMIN kylemanna/openvpn
Note, using the IP address is important in the likely event that DNS is broken until you connect to the VPN.
At this point, you should have a server running in the cloud.
Step 3 – Generate a Client Certificate
Change CLIENT
variable if you want more then one client as clients aren’t allowed simultaneous connections.
CLIENT=client1
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full $CLIENT nopass
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient $CLIENT | tee $CLIENT.ovpn
Step 4 – Copy the Client Certificate
This is up to you. I’d recommend scp
to copy the .ovpn
file to your laptop. You could also try to cat $CLIENT.ovpn
and copy-paste the certificate, but don’t screw it up.
Step 5 – Setup OpenVPN on Your Client
This is up to you as well, but I’ll give you a hint at what I’ve tried:
- Linux: Simple as
sudo openvpn --config $CLIENT.ovpn
after installing theopenvpn
package. - macOS: Tunnelblick Project and import the
$CLIENT.ovpn
package. - Windows: Try the installer from the OpenVPN project which needs to run
openvpn
as administrator. I don’t use Windows enough to figure out how to make this less painful, but it definitely works. - Android: Check out OpenVPN Connect App after copying it to your device using MTP file transfer.
- iOS: Check out OpenVPN Connect App. I have not tested this, let me know if it works.
Step 6 – Place an Inflight Phone Call
Well, maybe. You could do a VOIP phone call or a video chat, but please don’t. Your neighbors will hate you, for good reason. Surf the web and try to get to inbox zero.
I’m Too Lazy to Read
Well, I have a treat for you. A magic script that you can run as root (trust me! ha) and it’ll generate one certificate for you on your disposable $0.007/hr Digital Ocean droplet that you can destroy at the end of your flight.
Quick and easy via a little Github Gist:
curl -L https://gist.githubusercontent.com/kylemanna/3adcd465e709b8ff3300202f12fdfff1/raw/gogo-firewall-bypass.sh | sudo bash
Approximate expected output:
root@docker-512mb-sfo1-01:~# curl -L https://gist.githubusercontent.com/kylemanna/3adcd465e709b8ff3300202f12fdfff1/raw/gogo-firewall-bypass.sh
| sudo bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1376 100 1376 0 0 3831 0 --:--:-- --:--:-- --:--:-- 3843
[*] Generating server config for 504.731.333.274
Processing Route Config: '192.168.254.0/24'
Processing PUSH Config: 'block-outside-dns'
Processing PUSH Config: 'dhcp-option DNS 8.8.8.8'
Processing PUSH Config: 'dhcp-option DNS 8.8.4.4'
Successfully generated config
Cleaning up before Exit ...
[+] Generated server config for 504.731.333.274
[*] Initialzing PKI (insecurely) for the truely lazy
Generating a 2048 bit RSA private key
.............................................+++
..............................................................+++
writing new private key to '/etc/openvpn/pki/private/ca.key.XXXXpEDboo'
-----
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
............+.+..........+..................................................................................................................................................................................................+......................................................................................................................................................................+.................................................................................................................................+.......................................................+......................................................................................................+..........+...................................+..............................+...............................................+.....................................+.....................................................................................................................................................................+..........+......................................................................................................+.............................................................................................................................................................................................................................+......................................................................................................++*++*
Generating a 2048 bit RSA private key
..............+++
......................................................................................+++
writing new private key to '/etc/openvpn/pki/private/504.731.333.274.key.XXXXPgCELB'
-----
Using configuration from /usr/share/easy-rsa/openssl-1.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'504.731.333.274'
Certificate is to be certified until Nov 2 22:50:17 2026 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
[+] Initialized PKI magic
[*] OpenVPN server starting up
081347c0bb9fdd1b9c3c3536fc2eb519a2796fdc6d2f642db1380c81964aef36
[+] OpenVPN server up and running
[*] Generating client certificate for client1
Generating a 2048 bit RSA private key
............................................+++
..................................................+++
writing new private key to '/etc/openvpn/pki/private/client1.key.XXXXadBaIc'
-----
Using configuration from /usr/share/easy-rsa/openssl-1.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'client1'
Certificate is to be certified until Nov 2 22:50:20 2026 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
[*] Client certificate ready at client1.ovpn
_______________________________________
< Server up and running, happy surfing >
---------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/
||----w |
|| ||
[?] Copy client1.ovpn to your client
[x] Exiting
root@docker-512mb-sfo1-01:~# ls -l client1.ovpn
-rw-r--r-- 1 root root 4869 Nov 4 22:50 client1.ovpn
Have Fun. And as always, don’t be stupid with this new found capability.
Comments