From e9ad16b83ebd2c519b8b6f80e366a331da667c13 Mon Sep 17 00:00:00 2001 From: nxshock Date: Sun, 10 Mar 2024 18:18:23 +0500 Subject: [PATCH 1/9] Fix ACME challenge dir access --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index ec3811d..0cb5e53 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ func main() { slog.Debug("Starting HTTP listener", slog.String("addr", config.HttpListenAddr)) smux := http.NewServeMux() - smux.Handle(defaultAcmeChallengePath, http.StripPrefix(defaultAcmeChallengePath, http.FileServer(http.Dir(config.AcmeChallengePath)))) + smux.Handle(defaultAcmeChallengePath, http.FileServer(http.Dir(config.AcmeChallengePath))) smux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusMovedPermanently) }) From ea03e2c4fb0a0ed51cdb8924e57e16dbf126b287 Mon Sep 17 00:00:00 2001 From: nxshock Date: Sun, 10 Mar 2024 18:19:13 +0500 Subject: [PATCH 2/9] v0.0.4 release --- PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKGBUILD b/PKGBUILD index 52a5275..bb4e16f 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=gonx -pkgver=0.0.3 +pkgver=0.0.4 pkgrel=1 pkgdesc='Simple reverse proxy server' arch=('x86_64' 'aarch64') From 23fbce06c9aa32b9cf21c794e95ad325109d4801 Mon Sep 17 00:00:00 2001 From: NXShock Date: Mon, 2 Jun 2025 17:51:28 +0500 Subject: [PATCH 3/9] Add unix socket support --- gonx.conf | 1 + mapping.go | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/gonx.conf b/gonx.conf index 119ddc8..2b35a4c 100644 --- a/gonx.conf +++ b/gonx.conf @@ -7,3 +7,4 @@ AcmeChallengePath = "/var/lib/letsencrypt" # Path for ACME challenge files [TLS] # "www.example.com" = "file:/srv/http" # "git.example.com" = "tcp://127.0.0.1:8001" +# "unix.example.com" = "unix:///var/lib/app/app.socket" diff --git a/mapping.go b/mapping.go index 0fced0c..55dc715 100644 --- a/mapping.go +++ b/mapping.go @@ -39,7 +39,18 @@ func (h HostMapping) Add(host, outputUrlStr string) error { slog.Debug(err.Error()) continue } - go func() { _ = handleProxy(conn.(*tls.Conn), pd.Output) }() + go func() { _ = handleTcp(conn.(*tls.Conn), pd.Output) }() + } + }(pd) + case "unix": + go func(pd ProxyDirection) { + for { + conn, err := pd.listener.Accept() + if err != nil { + slog.Debug(err.Error()) + continue + } + go func() { _ = handleUnix(conn.(*tls.Conn), pd.Output) }() } }(pd) default: @@ -68,7 +79,7 @@ func handleTlsConn(conn *tls.Conn, hosts HostMapping) error { return nil } -func handleProxy(conn *tls.Conn, outputUrl *url.URL) error { +func handleTcp(conn *tls.Conn, outputUrl *url.URL) error { c, err := net.Dial(outputUrl.Scheme, outputUrl.Host) if err != nil { return fmt.Errorf("dial: %v", err) @@ -94,3 +105,30 @@ func handleProxy(conn *tls.Conn, outputUrl *url.URL) error { return nil } + +func handleUnix(conn *tls.Conn, outputUrl *url.URL) error { + c, err := net.Dial(outputUrl.Scheme, outputUrl.Host+outputUrl.Path) + if err != nil { + return fmt.Errorf("dial: %v", err) + } + defer c.Close() + + wg := new(sync.WaitGroup) + wg.Add(2) + + go func() { + defer wg.Done() + + _, _ = io.Copy(conn, c) + }() + + go func() { + defer wg.Done() + + _, _ = io.Copy(c, conn) + }() + + wg.Wait() + + return nil +} From 87698b6d5257b1b7df1d2fbfc4c22c9abf9b490e Mon Sep 17 00:00:00 2001 From: NXShock Date: Mon, 2 Jun 2025 17:53:17 +0500 Subject: [PATCH 4/9] v0.0.5 release --- PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PKGBUILD b/PKGBUILD index bb4e16f..6c92aae 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=gonx -pkgver=0.0.4 +pkgver=0.0.5 pkgrel=1 pkgdesc='Simple reverse proxy server' arch=('x86_64' 'aarch64') From b6c45bc386215f8accb2ee4c7ed3dd2a6475b9ae Mon Sep 17 00:00:00 2001 From: NXShock Date: Mon, 2 Jun 2025 17:56:16 +0500 Subject: [PATCH 5/9] Add unix socket example --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 350b26a..c4aca98 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ AcmeChallengePath = "/var/lib/letsencrypt" # Path for ACME challenge files # Map of hostname -> redirect URL [TLS] -"git.host.com" = "tcp://127.0.0.1:8001" # TCP redirect -"www.host.com" = "file:///srv/http" # simple static file server from `/srv/http` +"git.host.com" = "tcp://127.0.0.1:8001" # TCP redirect +"unix.host.com" = "unix:///var/lib/app/app.socket" # serve unix socket +"www.host.com" = "file:///srv/http" # simple static file server from `/srv/http` ``` From 1fe5a70c7c96af74e741231be9e01cf54e2e3e4f Mon Sep 17 00:00:00 2001 From: NXShock Date: Tue, 3 Jun 2025 10:35:39 +0500 Subject: [PATCH 6/9] Allow unix socket for systemd unit --- gonx.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gonx.service b/gonx.service index 7fbb58d..3ddbeac 100644 --- a/gonx.service +++ b/gonx.service @@ -40,7 +40,7 @@ UMask=0027 ProtectProc=noaccess ProcSubset=pid SystemCallFilter=~@clock @swap @reboot @raw-io @privileged @obsolete @mount @module @debug @cpu-emulation -RestrictAddressFamilies=~AF_UNIX AF_PACKET AF_NETLINK +RestrictAddressFamilies=~AF_PACKET AF_NETLINK UMask=0066 [Install] From c4c9bff7c60942656fd015c694143b8846a57740 Mon Sep 17 00:00:00 2001 From: NXShock Date: Tue, 3 Jun 2025 10:36:09 +0500 Subject: [PATCH 7/9] Return internal errors to clients --- PKGBUILD | 10 +++++----- mapping.go | 30 +++++++++++++++++++----------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 6c92aae..e8c483e 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -11,13 +11,13 @@ sha256sums=('SKIP') backup=("etc/$pkgname.conf") build() { - cd "$pkgname" - go build -o "$pkgname" -ldflags "-linkmode=external -s -w" -buildmode=pie -trimpath -mod=readonly -modcacherw + cd $pkgname + go build -o $pkgname -ldflags "-linkmode=external -s -w" -buildmode=pie -trimpath -mod=readonly -modcacherw } package() { cd "$pkgname" - install -Dm755 "$pkgname" "$pkgdir"/usr/bin/$pkgname - install -Dm644 "$pkgname.conf" "$pkgdir/etc/$pkgname.conf" - install -Dm755 $pkgname.service "$pkgdir"/usr/lib/systemd/system/$pkgname.service + install -Dm755 $pkgname $pkgdir/usr/bin/$pkgname + install -Dm644 $pkgname.conf $pkgdir/etc/$pkgname.conf + install -Dm755 $pkgname.service $pkgdir/usr/lib/systemd/system/$pkgname.service } diff --git a/mapping.go b/mapping.go index 55dc715..b1b65e7 100644 --- a/mapping.go +++ b/mapping.go @@ -30,7 +30,7 @@ func (h HostMapping) Add(host, outputUrlStr string) error { switch outputUrl.Scheme { case "file": server := http.Server{Handler: http.FileServer(http.Dir(outputUrl.Path))} - go func() { _ = server.Serve(pd.listener) }() + go server.Serve(pd.listener) case "tcp": go func(pd ProxyDirection) { for { @@ -39,7 +39,7 @@ func (h HostMapping) Add(host, outputUrlStr string) error { slog.Debug(err.Error()) continue } - go func() { _ = handleTcp(conn.(*tls.Conn), pd.Output) }() + go handleTcp(conn.(*tls.Conn), pd.Output) } }(pd) case "unix": @@ -50,7 +50,7 @@ func (h HostMapping) Add(host, outputUrlStr string) error { slog.Debug(err.Error()) continue } - go func() { _ = handleUnix(conn.(*tls.Conn), pd.Output) }() + go handleUnix(conn.(*tls.Conn), pd.Output) } }(pd) default: @@ -79,10 +79,14 @@ func handleTlsConn(conn *tls.Conn, hosts HostMapping) error { return nil } -func handleTcp(conn *tls.Conn, outputUrl *url.URL) error { +func handleTcp(conn *tls.Conn, outputUrl *url.URL) { + slog.Debug(fmt.Sprintf("%s -> %s", conn.RemoteAddr(), outputUrl.Host)) + c, err := net.Dial(outputUrl.Scheme, outputUrl.Host) if err != nil { - return fmt.Errorf("dial: %v", err) + writeError(conn, err) + conn.Close() + return } defer c.Close() @@ -102,14 +106,16 @@ func handleTcp(conn *tls.Conn, outputUrl *url.URL) error { }() wg.Wait() - - return nil } -func handleUnix(conn *tls.Conn, outputUrl *url.URL) error { +func handleUnix(conn *tls.Conn, outputUrl *url.URL) { + slog.Debug(fmt.Sprintf("%s -> %s", conn.RemoteAddr(), outputUrl.Host+outputUrl.Path)) + c, err := net.Dial(outputUrl.Scheme, outputUrl.Host+outputUrl.Path) if err != nil { - return fmt.Errorf("dial: %v", err) + writeError(conn, err) + conn.Close() + return } defer c.Close() @@ -129,6 +135,8 @@ func handleUnix(conn *tls.Conn, outputUrl *url.URL) error { }() wg.Wait() - - return nil +} + +func writeError(w io.Writer, err error) { + fmt.Fprintf(w, "HTTP/1.1 500 Internal Server Error\r\nConnection: Close\r\nContent-Type: text/plain\r\n\r\n%s", err) } From e4f9a1a130ec505dba31f5efdbbb2c4455614487 Mon Sep 17 00:00:00 2001 From: NXShock Date: Tue, 3 Jun 2025 11:40:52 +0500 Subject: [PATCH 8/9] Simplify listener code --- mapping.go | 52 ++++------------------------------------------------ 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/mapping.go b/mapping.go index b1b65e7..1c239ab 100644 --- a/mapping.go +++ b/mapping.go @@ -31,7 +31,7 @@ func (h HostMapping) Add(host, outputUrlStr string) error { case "file": server := http.Server{Handler: http.FileServer(http.Dir(outputUrl.Path))} go server.Serve(pd.listener) - case "tcp": + case "tcp", "unix": go func(pd ProxyDirection) { for { conn, err := pd.listener.Accept() @@ -39,18 +39,7 @@ func (h HostMapping) Add(host, outputUrlStr string) error { slog.Debug(err.Error()) continue } - go handleTcp(conn.(*tls.Conn), pd.Output) - } - }(pd) - case "unix": - go func(pd ProxyDirection) { - for { - conn, err := pd.listener.Accept() - if err != nil { - slog.Debug(err.Error()) - continue - } - go handleUnix(conn.(*tls.Conn), pd.Output) + go handleListener(conn.(*tls.Conn), pd.Output) } }(pd) default: @@ -79,41 +68,12 @@ func handleTlsConn(conn *tls.Conn, hosts HostMapping) error { return nil } -func handleTcp(conn *tls.Conn, outputUrl *url.URL) { - slog.Debug(fmt.Sprintf("%s -> %s", conn.RemoteAddr(), outputUrl.Host)) - - c, err := net.Dial(outputUrl.Scheme, outputUrl.Host) - if err != nil { - writeError(conn, err) - conn.Close() - return - } - defer c.Close() - - wg := new(sync.WaitGroup) - wg.Add(2) - - go func() { - defer wg.Done() - - _, _ = io.Copy(conn, c) - }() - - go func() { - defer wg.Done() - - _, _ = io.Copy(c, conn) - }() - - wg.Wait() -} - -func handleUnix(conn *tls.Conn, outputUrl *url.URL) { +func handleListener(conn *tls.Conn, outputUrl *url.URL) { slog.Debug(fmt.Sprintf("%s -> %s", conn.RemoteAddr(), outputUrl.Host+outputUrl.Path)) c, err := net.Dial(outputUrl.Scheme, outputUrl.Host+outputUrl.Path) if err != nil { - writeError(conn, err) + fmt.Fprintf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: Close\r\nContent-Type: text/plain\r\n\r\n%s", err) conn.Close() return } @@ -136,7 +96,3 @@ func handleUnix(conn *tls.Conn, outputUrl *url.URL) { wg.Wait() } - -func writeError(w io.Writer, err error) { - fmt.Fprintf(w, "HTTP/1.1 500 Internal Server Error\r\nConnection: Close\r\nContent-Type: text/plain\r\n\r\n%s", err) -} From 59cb02bf9483a613c26e7cad0bb84eaa5276d55a Mon Sep 17 00:00:00 2001 From: NXShock Date: Tue, 3 Jun 2025 18:12:17 +0500 Subject: [PATCH 9/9] Does not start TLS redirection on empty TLS config --- main.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 0cb5e53..9221fc9 100644 --- a/main.go +++ b/main.go @@ -38,10 +38,14 @@ func main() { os.Exit(1) } - err = app.restartTlsListener() - if err != nil { - slog.Error("Failed to start TLS listener", slog.String("err", err.Error())) - os.Exit(1) + if len(config.TLS) > 0 { + err = app.restartTlsListener() + if err != nil { + slog.Error("Failed to start TLS listener", slog.String("err", err.Error())) + os.Exit(1) + } + } else { + slog.Warn("TLS listener does not started because TLS redirection rules is empty") } go func() {