go-netcat
is a Golang-based netcat
tool designed to facilitate peer-to-peer communication. Its main features include:
-p2p
to automatically perform TCP/UDP NAT traversal and establish peer-to-peer connections without manual configuration, relying on public STUN and MQTT services for address exchange.-exec
to run the tool as a sub-service, supporting scenarios like traffic forwarding, Socks5 proxy, and HTTP file service with multiplexing capabilities.-exec
and -pty
, it provides a pseudo-terminal environment for interactive programs like /bin/sh
, enhancing shell control (supports TAB, Ctrl+C, etc.).raw
mode with -pty
, offering a native terminal-like experience when accessing a shell.nc
:
gonc www.baidu.com 80
gonc -tls www.baidu.com 443
gonc -psk .
to generate a high-entropy password to replace randomString
). This password is used for mutual discovery and certificate derivation, ensuring communication security with TLS 1.3.
gonc -p2p randomString
On the other side, use the same parameters (the program will automatically attempt TCP or UDP communication (TCP preferred), negotiate roles (TLS client/server), and complete the TLS protocol):
gonc -p2p randomString
Note that if the other end delays the running time, it will exit if it cannot find the other end to interact with information within about half a minute. Therefore, it also supports a waiting mechanism based on MQTT message subscription, using -mqtt-wait and -mqtt-hello to synchronize the timing of the two parties to start P2P. For example, the following uses -mqtt-wait to wait continuously,
gonc -p2p randomString -mqtt-wait
On the other side,
gonc -p2p randomString -mqtt-hello
-keep-open
, accepts only one connection; no authentication with -psk
):
gonc -tls -exec ":sh /bin/bash" -l 1234
gonc -tls -pty x.x.x.x 1234
randomString
is used for authentication, ensuring secure communication with TLS 1.3):
gonc -exec ":sh /bin/bash" -p2p randomString
On the other side:
gonc -pty -p2p randomString
/dev/zero
and /dev/urandom
):
gonc.exe -send /dev/zero -P x.x.x.x 1234
Example output:
IN: 76.8 MiB (80543744 bytes), 3.3 MiB/s | OUT: 0.0 B (0 bytes), 0.0 B/s | 00:00:23
On the receiving side:
gonc -P -l 1234 > NUL
gonc -p2p randomString -socks5server
gonc -p2p randomString -socks5local-port 3080
gonc -p2p randomString -httpserver c:/RootDir
gonc -p2p randomString -httplocal-port 9999
Support recursive download of all files with resume capability:
gonc -p2p randomString -download c:/SavePath
-exec
to flexibly configure the application to provide services for each connection. For example, instead of specifying /bin/bash
for shell commands, it can also be used for port forwarding. However, the following example starts a new gonc
process for each connection:
gonc -keep-open -exec "gonc -tls www.baidu.com 443" -l 8000
gonc -keep-open -exec ":nc -tls www.baidu.com 443" -l 8000
gonc -x s.s.s.s:port x.x.x.x 1234
-e :s5s
to provide standard Socks5 service. Support -auth
to set a username and password for Socks5. Use -keep-open
to continuously accept client connections to the Socks5 server. Thanks to Golang’s goroutines, it achieves good multi-client concurrency performance:
gonc -e ":s5s -auth user:passwd" -keep-open -l 1080
Secure Socks5 over TLS: Since standard Socks5 is unencrypted, use -e :s5s
with -tls
and -psk
to customize secure Socks5 over TLS communication. Use -P
to monitor connection transmission information, and -acl
to implement access control for incoming connections and proxy destinations. For the acl.txt
file format, see acl-example.txt.
gonc.exe -tls -psk randomString -e :s5s -keep-open -acl acl.txt -P -l 1080
On the other side, use :nc
(built-in nc command) to convert Socks5 over TLS to standard Socks5, providing local client access on 127.0.0.1:3080:
gonc.exe -e ":nc -tls -psk randomString x.x.x.x 1080" -keep-open -l -local 127.0.0.1:3080
Assist WireGuard in NAT Traversal to Form a VPN
On the passive (listening) side, PC-S, run the following command (using the WireGuard peer’s public key as the randomString, and assuming WireGuard is listening on port 51820):
gonc -p2p <PublicKey-of-PS-S> -mqtt-wait -u -k -e ":nc -u 127.0.0.1 51820"
On the active (initiating) side, PC-C, set the WireGuard peer (PS-S)’s Endpoint to 127.0.0.1:51821, with its own WireGuard interface listening on 51820. Then run the following command. The -k flag allows gonc to automatically reconnect if the network drops:
gonc -p2p <PublicKey-of-PS-S> -mqtt-hello -u -k -e ":nc -u -local 127.0.0.1:51821 127.0.0.1 51820"
A SOCKS5 server with UDP ASSOCIATE support running on a public IP is sufficient as a relay. You can also run gonc’s built-in SOCKS5 proxy on your own VPS to act as a relay server.
The following command starts a SOCKS5 proxy that only supports UDP forwarding. The -psk and -tls options enable encryption and PSK-based authentication. Note: Don’t just open port 1080 in your firewall—UDP forwarding uses random ports for each session.
gonc -e ":s5s -u -c=0" -psk <password> -tls -k -l 1080
When P2P fails, you only need one side of gonc to retry the P2P process using the -x option to route through the SOCKS5 relay:
gonc -p2p <randomString> -x "-psk <password> -tls <socks5server-ip>:1080"
Alternatively, you can use a standard SOCKS5 proxy server that supports UDP forwarding:
gonc -p2p <randomString> -x "<socks5server-ip>:1080" -auth "user:password"
For example, if both peers are behind symmetric NATs and P2P fails, having just one side use a SOCKS5 UDP relay effectively changes its NAT behavior to “easy,” making it much easier to establish a connection. The data remains end-to-end encrypted.
"tcp://turn.cloudflare.com:80",
"udp://turn.cloudflare.com:53",
"udp://stun.l.google.com:19302",
"udp://stun.miwifi.com:3478",
"global.turn.twilio.com:3478",
"stun.nextcloud.com:443",
"tcp://broker.emqx.io:1883",
"tcp://test.mosquitto.org:1883",
gonc classifies NAT types into three categories:
Easy: A single internal port maps to the same external port across multiple STUN servers
Hard: A single internal port maps to a consistent but different external port across STUN servers — harder than type 1
Symmetric: A single internal port maps to different external ports depending on the destination — the most difficult type
To handle these NAT types, gonc employs several traversal strategies:
Uses multiple STUN servers to detect NAT behavior and identify multi-exit IP scenarios
Prefers IPv6 connections when both sides support it (e.g., TCP6-to-TCP6 direct dial)
Both peers listen on TCP while simultaneously dialing each other to increase TCP hole punching success
The peer with the easier NAT delays its initial UDP packet to avoid triggering port changes on the harder side
The peer with the harder NAT sends UDP packets with a low TTL to reduce interference from the remote firewall
As a last resort, uses a “birthday paradox” strategy: the harder side uses 600 random source ports, and the other side tries 600 random destination ports, increasing the chance of a successful UDP port collision