I’ve been hosting minecraft servers for my kids since around 2019. First on my OpenBSD home server for local play, and then on Shockbyte for ease of playing with friends. Overall the minecraft hosting experience on shockbyte has been pretty great, but I recently discovered Exaroton and they have a feature that lets you only spin up your minecraft server when you’re using it (automatically), and will automatically shut it down for you when you’re not. I noticed recently that shockbyte also has something similar called “hibernation”, but it seems like shockbyte keeps charging you even if your server is hibernating, while exaroton does not.
What this means for me, is that I can have a bunch of different minecraft servers available all the time, but only get charged when people are actually playing on them. My kids like to play with certain friends on one world, and with other friends on another, and though I’ve tried to convince them that a minecraft world is huge and that there’s plenty of space for all the friends to play together on the same server, they weren’t having it. They want separation of concerns.
I spun up a few minecraft servers for them to test out, and at first it seemed like things were working great. I pointed a subdomain over to them so it was easier to share with friends and we were off to the races.
Something weird happened once I enabled the “auto off” functionality though. For some reason my home network had a hard time connecting to the minecraft servers now. The way the feature works is if your server is off when you first connect to it, you are dropped into a minecraft “waiting” lobby, where you’re met with a nice sign telling you that your server is spinning up, and to please standby. Once your server is up and running, the minecraft client automatically attempts to connect to the now available server. This bit is what’s not working from my home network.
It seems to work fine for our friends, they are able to connect, see the waiting lobby, and then after a few seconds, connect to the actual minecraft world. For me however, every time the client tries to transfer me to the new world it just hangs forever and never connects. Eventually it times out, the server shuts down (because no one has connected to it for 5 minutes), and I get dumped back to the “pick a server” screen in minecraft.
I haven’t spent enough time trying to figure out the root cause, since I have a workaround that seems to fix the problem. If I connect to my VPN first, everything works as expected.
This makes sense as the network configurations for my home network and my VPN are different. The VPN uses different DNS servers than what I use at home, and the firewall configurations are different.
I’m not sure which of the two issues it might be, but it should be easy enough to figure that out. First thing is first, I try updating my /etc/resolv.conf and put in the cloudflare DNS server (1.1.1.1) directly. This is what exaroton suggests you use if you’re having problems connecting to their servers. This doesn’t seem to change anything though so I guess the problem is with the firewall.
I’m running OpenBSD’s pf, so I check on both the VPN exit node and my home router to see what the differences might be. My VPN firewall is pretty sparse:
# $OpenBSD: pf.conf,v 1.55 2017/12/03 20:40:04 sthen Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf
set skip on { lo tun2 }
block return # block stateless traffic
pass # establish keep-state
# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010
ext_if2 = "vio0"
vpn_if = "pppx"
vpn_net = "10.0.0.0/24"
pass in quick on egress proto udp to port 51820
pass in on $ext_if2 proto esp
pass in on $ext_if2 proto udp to port { isakmp, ipsec-nat-t }
pass on enc0 keep state (if-bound)
pass on $vpn_if from $vpn_net
pass on $vpn_if to $vpn_net
pass on wg0
match out on $ext_if2 from $vpn_net nat-to ($ext_if2) set prio (3,4)
match out on egress inet from (tun2:network) nat-to (egress:0)
match out on egress inet from (wg0:network) nat-to (egress:0)
My home firewall is a bit more involved as it’s handling NAT, rate limiting of ssh accesses, queueing to reduce buffer bloat, and a few other things besides:
# $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf
#
# Ansible managed
# macros
ext_if="em3"
int_if="em1"
int2_if="em2"
int3_if="em0"
tailnet="tun0"
localnet=$int_if:network
localnet2=$int2_if:network
localnet3=$int3_if:network
#tcp_services="{ smtp }"
tcp_rate_limited="{ ssh }"
icmp_types="echoreq"
# tables
table <bruteforce> persist
# queues for managing bufferbloat
queue outq on $ext_if flows 1024 bandwidth 480M max 490M qlimit 1024 default
queue inq on $int_if flows 1024 bandwidth 480M max 490M qlimit 1024 default
set block-policy return
set loginterface em3
set skip on lo0
set state-defaults pflow
#match in all scrub (no-df random-id max-mss 1440)
match in all
match out on $ext_if inet from !($ext_if:network) to any nat-to ($ext_if:0)
block in log
block quick from <bruteforce>
pass out quick
antispoof quick for { lo $int_if }
antispoof quick for { lo $int2_if }
antispoof quick for { lo $int3_if }
pass in on $ext_if inet proto tcp to port $tcp_rate_limited \
flags S/SA keep state \
(max-src-conn 5, max-src-conn-rate 5/60, \
overload <bruteforce> flush global)
#pass in on $ext_if inet proto tcp from any to ($ext_if) \
#port $tcp_services
pass in inet proto icmp all icmp-type $icmp_types
pass in on $tailnet
pass in on $int_if
pass in on $int2_if
pass in on $int3_if
pass in on $ext_if proto tcp from any to any port smtp \
divert-to 127.0.0.1 port spamd
pass out on $int_if to $localnet
pass out on $int2_if to $localnet2
pass out on $int3_if to $localnet3
pass out on $ext_if proto { tcp udp icmp } all modulate state
At this point, I figured “I should see what ChatGPT thinks of all this”, and so I fed it the post so far. It suggested that I try allowing all traffic from my laptop (the minecraft client) through my firewall with the following rule:
match out on $ext_if from 192.168.1.42 nat-to ($ext_if)
I reloaded my pf configuration pfctl -f /etc/pf.conf
but nothing changed.
ChatGPT suggested a few other tweaks to the firewall, but nothing changed.
Eventually we ran a few nmap
scans to see if I could even access the IP/port
combination on the host server:
bluebox# nmap -Pn gilamonster.exaroton.host -p 21532
Starting Nmap 7.92 ( https://nmap.org ) at 2025-08-03 15:45 EDT
Nmap scan report for gilamonster.exaroton.host (37.228.148.2)
Host is up (0.0032s latency).
PORT STATE SERVICE
21532/tcp filtered unknown
Nmap done: 1 IP address (1 host up) scanned in 1.02 seconds
And then from my vpn server:
vpn# nmap -Pn gilamonster.exaroton.host -p 21532
Starting Nmap 7.92 ( https://nmap.org ) at 2025-08-03 19:47 UTC
Nmap scan report for gilamonster.exaroton.host (37.228.148.2)
Host is up (0.031s latency).
PORT STATE SERVICE
21532/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 0.84 seconds
This shows that I can reach the host/port combo from my VPN server, but not from my home router. Though I already knew this, now that I had my firewall set to allow all traffic from my laptop out, this suggested that maybe the issue wasn’t with my firewall after all.
In order to narrow down the problem further, I tried connecting my laptop directly to my ISP (bypassing my firewall completely) and that also was unsuccessful which seemed to indicate that perhaps my ISP was blocking me from accessing these minecraft servers.
ChatGPT suggested I send the following email to my ISPs customer support:
Subject: Outbound Port Filtering or CGNAT Interference?
Hi there,
I'm trying to connect to a Minecraft server hosted by Exaroton on port 21532,
but the connection never completes from my home network. When I test with nmap,
it shows the port as filtered, and I'm unable to connect even when directly
plugged into the ISP modem.
However, when I connect to the same server using a VPN (which exits through a
different network), it works perfectly.
This makes me wonder if there’s any outbound port filtering, carrier-grade NAT,
or firewalling happening upstream that might be affecting outbound connections
to higher TCP ports like this one.
Happy to provide more info if needed — thanks in advance for your help!
gabe.
And the next morning, I got a response:
Hello,
Our IT support team has confirmed that the issue is due to the fact that we’ve
purchased IP addresses from around the world lately. Some of these IPs do not
yet have full access to certain services.
This should be resolved by October.
Alternatively, we can assign you a static IP address that already has full
access, but please note that this would come at an additional cost of
approximately $10 per month.
Let us know how you’d like to proceed.
OK! At least now I knew that the issue wasn’t on my end.
Now, what to do about it? Since it was working if I used my VPN, I figured there must be a way to configure things so that my router would send the minecraft server traffic destined for exaraton out over my VPN but leave the rest of my traffic alone. I also didn’t really want to pay an extra 10.00 a month to my ISP when I thought I could probably work around the problem myself in not too much time. I’m not a networking expert (I just play one on TV), but I have been futzing around with computers for a pretty long time, so I knew there must be a way to leverage something like my existing wireguard vpn, tailscale network, or even SSH tunnels to do what I needed.
Since I’m not an expert, I poked ChatGPT again to see what it thought.
ChatGPT offered me a few options:
Option 1: SOCKS proxy via ssh -D + Minecraft client config
Option 2: Use Tailscale or WireGuard site-wide
Option one would mean that I’d need to setup a SOCKS proxy and then configure each minecraft client to use that proxy, that sounded like too much work.
Option two meant I either had to get a wireguard client up and running on my home router, or leverage the tailscale network that was already running on my home router. I opted for the second option as I thought that would be the easiest and get me up and running with the least effort.
While I was working with ChatGPT to get the tailscale solution running, I ran into a few issues.
ChatGPT started by giving me some very reasonable advice, told me I should add a table to my pf.conf that held the exaroton IP range that the minecraft servers were generally in:
table <exaroton_ips> persist { 37.228.144.0/20 }
match out on tun0 from 192.168.1.0/24 to <exaroton_ips> nat-to (tun0)
This seemed pretty sane, so I plugged that into my pf.conf
and tested it
(always test your pf.conf before executing it, ask me how I know!):
pfctl -nf /etc/pf.conf
This just makes sure the pf.conf
file is actually valid it doesn’t stop you from
doing something dumb. Once that came back clean a quick pfctl -f /etc/pf.conf
to reload the rule set and we could continue.
As I was doing this, I wondered how exactly I could route traffic out of my network while connected to tailscale but not using an exit node. I wasn’t quite sure how that was supposed to work, and when I asked ChatGPT this is what it said:
Me: can I route traffic out though tailscale if I'm just connected to it and not
using it as an exit node?
ChatGPT said:
Ah — this is an important distinction.
Short answer:
No, not automatically.
If your OpenBSD gateway is just connected to Tailscale (i.e., it's in
the mesh, but not routing through an exit node), then traffic won’t
leave via Tailscale by default, even with NAT rules.
Well, why are you telling me to do that then? ChatGPT pivoted at this point and
told me that what I needed to do to make this work, was to use an exit node, but
tell tailscale not to send all traffic out via that exit node, and then
configure OpenBSD to only route some traffic through it. ChatGPT told me I
needed to use the following tailscale command to make this work: tailscale up --exit-node=100.x.x.x --exit-node-allow-lan-access
so that’s what I tried.
Unfortunately, I got an error and when I mentioned that to ChatGPT it said:
Me: Doesn't seem to be working. --exit-node-allow-lan-access doesn't seem to be
a valid flag.
ChatGPT said: You're absolutely right — --exit-node-allow-lan-access is not supported on
OpenBSD (yet), and that causes a silent failure or default fallback.
🤦 so, that’s not going to work then.
ChatGPT then suggested this workaround:
✅ Workaround: Use a separate VPS as a manual NAT jump host
Instead of trying to rely on Tailscale's exit node features (which are limited on OpenBSD), you can build your own mini exit node using your VPS.
👇 Here’s the plan:
SSH from your OpenBSD gateway to your VPS
Create a reverse tunnel or regular TCP forward (like ssh -L)
Use PF to redirect Minecraft traffic to the local side of the tunnel
Let the VPS forward it out to Exaroton
This seemed like a bit of overkill, especially given that I’d already mentioned that I also had a wireguard vpn that I could leverage (I didn’t do that first because the client hadn’t been setup yet on my home router). Thankfully, ChatGPT also said this:
Alternative: Set up a real WireGuard exit node on the VPS
I told ChatGPT that I was already running wireguard and just needed to configure a client on my home router. ChatGPT wanted me to install wireguard-tools, but that shouldn’t be needed as OpenBSD has full wireguard support built into the kernel already. You can just use the normal /etc/hostname.if files to configure it.
It’s good that I knew that because ChatGPT really wanted me to install wireguard-tools. It took me a few tries, but I was able to get the wireguard client up and running pretty easily, I even discovered that I’d already generated the client secret key and configuration for my router, I’d just never configured it.
This is what I put in my /etc/hostname.wg0
file:
bluebox# cat /etc/hostname.wg0
wgkey <REDACTED PRIVATE KEY>
wgpeer tDPdmpq44iiUtsTj16MscRGQTPe0dAeaYpiRhckVe3M= wgendpoint <REDACTED IP> 51820
wgaip 0.0.0.0/0
inet 10.11.12.15/24
up
Then I ran sh /etc/netstart wg0
to start networking on the wg0 interface. The
interface came up, and it looked like it was working (Narrator: It was not, in
fact working).
ChatGPT had some nice feedback for me when I told it than I was ignoring it’s suggestion to install wireguard-tools and instead just using the in kernel wireguard:
Nice — you’re using the in-kernel WireGuard implementation on OpenBSD, which is totally solid and performs better than wg-quick.
So, good that it knows that, but why did it tell me to use wireguard-tools? LLMs are not to be trusted.
I double checked my firewall rules and attempted to connect to the minecraft server, still no luck. ChatGPT helpfully informed me that I had forgotten to specify a route in my /etc/hostname.wg0! It suggested I put the wrong thing first, but then once that didn’t work, it suggested the right thing:
!route add -inet 37.228.144.0/20 10.11.12.1
That sort of worked! Except that I still couldn’t connect to the minecraft servers I wanted to connect to. :thinkingface:
ChatGPT suggested I run a tcpdump on the firewall to see what was going on with my packets:
bluebox# tcpdump -ni wg0 port 21532
tcpdump: listening on wg0, link-type LOOP
18:49:53.439527 192.168.1.42.41806 > 37.228.148.16.21532: S
3528081060:3528081060(0) win 64240 <mss 1460,sackOK,timestamp 352037926
0,nop,wscale 7> (DF) [tos 0x10]
18:49:54.473997 192.168.1.42.41806 > 37.228.148.16.21532: S
3528081060:3528081060(0) win 64240 <mss 1460,sackOK,timestamp 352038961
0,nop,wscale 7> (DF) [tos 0x10]
18:49:55.496920 192.168.1.42.41806 > 37.228.148.16.21532: S
3528081060:3528081060(0) win 64240 <mss 1460,sackOK,timestamp 352039984
0,nop,wscale 7> (DF) [tos 0x10]
Apparently, my packets were going out, but not coming in.
ChatGPT told me to double check my firewall settings to make sure the NAT was working properly, but my gut was telling me I needed to double check that the wireguard tunnel was working properly first, so that’s what I did.
I tried to ping my wireguard router (10.11.12.1) and got no response, and when I
checked the output of ifconfig wg0
I noticed that packets were going out the
door, but no packets were coming back in:
bluebox# ifconfig wg0
wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
index 10 priority 0 llprio 3
wgport 9680
wgpubkey AJcUfPbBDZ5yYIENBUIKbBcBPBpsC4YTskHiqV+woCY=
wgpeer tDPdmpq44iiUtsTj16MscRGQTPe0dAeaYpiRhckVe3M=
wgendpoint 45.77.4.217 51820
tx: 26492, rx: 0
wgaip 0.0.0.0/0
groups: wg
inet 10.11.12.15 netmask 0xffffff00 broadcast 10.11.12.255
tx: 26492, rx: 0
- That’s not good. That means, I’ve transmitted (tx) 26492
packets (bytes maybe? I’m not sure) but received (rx) 0. So, the tunnel isn’t
working.
I double checked the settings, and WHOOPS I accidentally entered an incorrect endpoint IP. What happened was the configuration file for my home router had been generated when I was using a different VPS (Virtual Private Server). When I migrated my VPN server to a different region (so my dad could watch his baseball games) I never adjusted the old configuration files.
Once I put in the correct IP for the VPN server, BOOM! I was able to ping the VPN router 10.11.12.1 from my firewall machine. I could tell we were getting close now, but still no minecraft.
I told ChatGPT and ChatGPT wanted to fix my NAT settings again, but at this point I was pretty sure that wasn’t the problem. I decided to just dump my tweaked pf.conf into ChatGPT again so it could have another look and it immediately noticed that the IP range we had initially used for the minecraft servers (37.228.144.0/29) was too restrictive, and didn’t include the new IP that I was getting (37.228.148.21).
ChatGPT suggested a small tweak to the IP range (37.228.144.0/20), I restarted
pf pfctl -f /etc/pf.conf
and like magic, I was connected to the minecraft server!
Now, in theory, and assuming the IPs for the exaraton servers aren’t too spread out, my kids should be able to play minecraft with their friends w/out having to bug me to enable the VPN for them and I can move the one remaining minecraft server from shockbyte to exaroton to save a few bucks a month!
Overall, I’d say ChatGPT was a helpful debugging assistant, though it did tend to get quite verbose, and led me down a few unhelpful side quests. We managed to figure it out together, and I think having it as a partner did help me to stay on-task. It would have been nice if it didn’t tell me to do things that were impossible on OpenBSD, and if I didn’t know better this probably would have taken a lot longer but it did help me stay focused on the problem and it was super handy to have quick “try this tcpdump command” pointers at the ready.
Reply by Email