Open port on mac for Go program running on VSCode
TLDR; Programs in ~/Desktop and some other ~/* sub directories don’t trigger firewall permission dialog.
Problem & Workaround
Mac by default has firewall rules that block incoming network connections. Usually this isn’t a problem because the OS will pop a up a dialog asking to allow incoming network connections.
For example, the following command will launch a server at port 8000.
# start an HTTP server
python3 -m http.server 8000
The command will trigger the following permission dialog. You can simply click on “Allow” to open up the port.

Same can be done on VSCode as well with the following launch.json
{
"name": "test server",
"request": "launch",
"module": "http.server",
"type": "debugpy",
"args": [
"8000",
]
}
So far so good, no problema.
Now, let’s try this with a server written in go.
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
log.Fatal(http.ListenAndServe(":8000", nil))
}
If we run this from the command line, we get the same dialog
go run .
But, if we try running it on VSCode, for reasons that I don’t know, the dialog doesn’t show up and incoming network connections are blocked by the firewall.
We can solve this using a command line tool called “socat” which can relay packets sent to one port to another. It’s like ssh port forward but from local to local.
# Install socat
brew install socat
# Relay incoming packets to port 8080 to port 8000
socat TCP-LISTEN:8080,fork TCP:localhost:8000
This way the permission dialog will pop up and you can allow it to accept incoming network access.
Mystery Solved (kind of…)
I did a little more digging trying to find out why the dialog doesn’t pop up.
First, I though I must have denied the program before so that the dialog won’t show up again. The allowed/denied programs are saved in /Library/Preferences/com.apple.alf.plist by /usr/libexec/ApplicationFirewall/socketfilterfw command. Although I couldn’t find it in the list, I cleared the list and rebooted just to be sure. It didn’t solve the problem.
Then I looked into the binary. When launched from VSCode, it builds the project as __debug_bin
in the project directory. And execute it via LLDB /Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/debugserver. This file binary file is only available when the program is launched by VSCode. I tried running this __debug_bin
from command line and it indeed did not pop up the dialog.
I then did a bit more experiment. I copied this binary and stopped VSCode and tried to move it to different paths to see if the dialog pops up. The dialog pops up when I move the binary to /Applications, /tmp, ~/, no dialog when I move it to ~/Desktop, ~/Downloads.
Conclusion
It had nothing to do with VSCode or Go after all, it just depended on where I put the damn binary! Remember the first commands that triggered the dialog? They were python
and go
commands that reside in /usr/local/bin
that’s why they worked. So thanks to whatever Apple magic, programs that placed under certain directories such as ~/Desktop won’t trigger firewall permission dialog. What you need to do is to move your project directory outside to somewhere else.
In the end, I moved the project directory to ~/projects and this dialog finally popped up. What a waste of time 😵💫
