📚 macOS Application Firewall: Allowing Incoming Connections for Python Command Line Servers
Problem Description
When running a local development server using a command-line interpreter (like python3 -m http.server, Node.js, Ruby, etc.) on macOS, the built-in Application Firewall often fails to prompt the user to "Allow incoming connections".
Get SDNTechForum’s stories in your inbox
Join Medium for free to get updates from this writer.
As a result, other devices on the local network (or even a browser accessing the Mac’s IP address) cannot connect to the server, as the firewall silently blocks the connection. Manually selecting the script file (.py file) in the Firewall Options does not work because it is not the true executable.
Technical Cause: The Application Firewall Logic
The macOS Application Firewall operates on a per-executable binary basis, not a per-script or per-port basis.
- When a connection attempt is made, the firewall looks for the primary binary that opened the listening port.
- For a Python server, the primary binary is the Python interpreter itself (e.g.,
/usr/bin/python3,/usr/local/bin/python3, or a virtual environment executable). - If the interpreter’s full path has not been specifically allowed or signed, the firewall often refuses to prompt the user or allow the connection. The firewall cannot assign a permanent exception to a generic script being run by the interpreter.
Solution: Two Methods to Create an Exception
Method 1: Whitelist the Interpreter Executable
Manually add the full path to the Python interpreter (the executable binary) that is running the server to the firewall’s allowed list.
- Find the Executable Path: Run the server, then open a new Terminal window and use the following command to identify the exact running executable:
ps aux | grep "python"- Look for the full path to the
pythonorpython3binary (e.g.,/usr/local/opt/python@3.11/bin/python3.11). - Add the Exception:
Go to System Settings > Network > Firewall > Options…
Click the + (Add) button.
Press Command-Shift-G to “Go to Folder” and paste the full path to the Python executable binary.
Select the binary and ensure its permission is set to Allow incoming connections.
Method 2: Use socat as a Relaying Proxy (Recommended Workaround)
Use the utility socat to act as the listening process. Since socat is a standalone binary specifically designed for socket operations, the firewall will reliably prompt you for permission for socat, and once allowed, socat can forward traffic to your local server.
- Install
socat(if needed, typically via Homebrew):
brew install socat- Start your Server Locally: Start your Python server on a port that is only listening on the local machine (
localhostor127.0.0.1). We'll use port8000as an example: - Bash
python3 -m http.server 8000- Run
socatto Listen and Relay: Open a second Terminal window and runsocatto listen on a public port (e.g.,8080) and redirect all incoming traffic to the internal port (8000):
socat TCP-LISTEN:8080,reuseaddr,fork TCP:localhost:8000- Grant Permission: The first time you run the
socatcommand, the macOS firewall will pop up the "Allow incoming connections" dialog for thesocatexecutable. Grant the permission. - Once granted, external clients can connect to your Mac on port
8080, and the traffic will be seamlessly passed to your Python server running internally on port8000.
#Firewall #Networking #CyberSecurity #TechTip #macOS #Apple #MacBook
🙏 Thank you 🙏 for being a part of the SDNTechForum community! 💖🤖💖
Before you go, don’t forget to leave some claps 👏👏👏 (≥50 would be amazing 😉) and follow me ️🙏.
For further reading, explore my in-depth analysis on Medium and YouTube.









