When working with local development servers, we often need to forward traffic from one IP/port combination to another. On Linux systems, this is commonly achieved using iptables
NAT rules. The equivalent functionality in macOS requires a different approach due to differences in the underlying networking stack.
Apple has transitioned from ipfw
to pf
(Packet Filter) as the primary firewall and NAT solution. Here's how to achieve the desired port forwarding:
# Create or edit /etc/pf.conf
echo '
rdr pass on lo0 inet proto tcp from any to 192.168.99.100 port 80 -> 127.0.0.1 port 8000
' | sudo tee -a /etc/pf.conf
# Enable and load the rules
sudo pfctl -e
sudo pfctl -f /etc/pf.conf
To verify the rules are active:
sudo pfctl -s nat
Common issues to check:
- Ensure the
lo0
interface exists (ifconfig lo0
) - Check for syntax errors (
sudo pfctl -vnf /etc/pf.conf
) - Verify the target service is running (
netstat -an | grep 8000
)
For developers who prefer user-space solutions:
Using socat
brew install socat
socat TCP4-LISTEN:80,fork,reuseaddr,bind=192.168.99.100 TCP4:127.0.0.1:8000
Using nginx as reverse proxy
brew install nginx
# Add to /usr/local/etc/nginx/nginx.conf
server {
listen 192.168.99.100:80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8000;
}
}
To make the pf
solution persistent across reboots:
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.pfctl.plist
When working with local development environments, we often need to forward traffic from one IP/port to another. On Linux, this is straightforward with iptables
, but macOS requires different tools.
macOS provides two main firewall/forwarding mechanisms:
1. PF (Packet Filter) - The newer, recommended system (since macOS 10.10)
2. IPFW - The legacy system (deprecated but still available)
Create or edit /etc/pf.conf
:
# Enable packet forwarding
sysctl -w net.inet.ip.forwarding=1
# Add these rules to pf.conf
rdr pass on lo0 inet proto tcp from any to 192.168.99.100 port 80 -> 127.0.0.1 port 8000
pass in quick proto tcp from any to 127.0.0.1 port 8000
Then load the rules:
sudo pfctl -ef /etc/pf.conf
For older macOS versions, IPFW can work but has limitations:
sudo ipfw add fwd 127.0.0.1,8000 tcp from any to 192.168.99.100 80
Check if the rules are active:
# For PF
sudo pfctl -s nat
# For IPFW
sudo ipfw show
Test with curl:
curl -I http://192.168.99.100
- Ensure your dev server is running on 127.0.0.1:8000
- Check macOS firewall isn't blocking the traffic
- Verify the interface name (lo0 vs en0 etc.)
For persistent rules across reboots, add the PF configuration to /etc/pf.conf
and create a launch daemon or use anchors
for more complex setups.