Added docs and some minor improvements to code

Darshil Chanpura 1 year ago
parent 003b74cd8a
commit 67c0f5a283

@ -0,0 +1,39 @@
# Tun-Tana-Tun (टन-टना-टन)
This project is a simple TCP Proxy allows bring remote ports listening on localhost.
This main reason why this project exists is to be used with [gokrazy](
on Raspberry Pi.
# Usage
Usage of tuntanatun:
Enable Logs
-local string
Local Address (default "localhost:9999")
-remote string
Remote Address (default "localhost:80")
# A simple use case
By using gokrazy there are challenges in creating a network interface and running [Tailscale]( on it, so we use userspace networking mode of Tailscale.
There are work-arounds in accessing the peers using HTTP_PROXY variable, like most of the HTTP Requests can use this variable and proxy it through, the problem comes when there is a need to connect to a port with non-HTTP like connecting to a Database.
The simple solution is to use `SOCKS` proxy, which allows all traffic to be proxied, and fortunately `tailscaled` allows setting a `SOCKS5` proxy listener/server through command line arguments.
Now we can try to connect to the desired service/server in VPN, but alas, there's one more problem.
To use this proxy the program should respect the proxy variable like `ALL_PROXY`, we know `HTTP_PROXY` is always used for any `net/http` functions but as this `SOCKS` proxy implementation is not yet in standard library normal packages don't use it.
One option is to change the service code to use this proxy implementation, which is simply a change in `net.Dialer` using `proxy.FromEnvironment()`. Which requires changes in possibly everything and building again.
Another option is to bring that port, from remote server to `localhost`. This is also called tunneling, or port forwarding. We use a local port and connect to remote host:port and proxy it.
Following diagram shows this in action.

Binary file not shown.


Width:  |  Height:  |  Size: 65 KiB

File diff suppressed because one or more lines are too long


Width:  |  Height:  |  Size: 16 KiB

@ -2,7 +2,6 @@
package main
import (
@ -12,8 +11,11 @@ import (
var localAddr *string = flag.String("local", "localhost:9999", "local address")
var remoteAddr *string = flag.String("remote", "localhost:80", "remote address")
var (
localAddr = flag.String("local", "", "Local Address")
remoteAddr = flag.String("remote", "", "Remote Address")
debug = flag.Bool("debug", false, "Enable Logs")
func main() {
@ -21,19 +23,21 @@ func main() {
listener, err := net.Listen("tcp", *localAddr)
if err != nil {
for {
conn, err := listener.Accept()
log.Println("New connection", conn.RemoteAddr())
if *debug {
log.Println("New connection", conn.RemoteAddr())
if err != nil {
log.Println("error accepting connection", err)
go func() {
defer conn.Close()
conn2, err := proxy.Dial(context.Background(), "tcp", *remoteAddr)
conn2, err := proxy.FromEnvironment().Dial("tcp", *remoteAddr)
if err != nil {
log.Println("error dialing remote addr", err)
@ -43,7 +47,9 @@ func main() {
go copy(closer, conn2, conn)
go copy(closer, conn, conn2)
log.Println("Connection complete", conn.RemoteAddr())
if *debug {
log.Println("Connection complete", conn.RemoteAddr())