From 44958b603f66601a83d99da547f1194cff7ffa70 Mon Sep 17 00:00:00 2001 From: Cedric Staub Date: Sat, 29 Nov 2025 16:13:57 -0800 Subject: [PATCH 1/6] Enable landlock by default if possible (best-effort mode) --- README.md | 2 +- landlock_linux.go | 19 +++++++------------ landlock_other.go | 4 +--- main.go | 32 +++++++++++++++++++++----------- main_test.go | 9 --------- tests/common.py | 7 ------- 6 files changed, 30 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 49feb5ac9e..8e52520b91 100644 --- a/README.md +++ b/README.md @@ -355,4 +355,4 @@ this option. ### Landlock Support -Ghostunnel can use [Landlock](https://landlock.io) to limit process privileges on Linux. Landlock can be enabled using the `--use-landlock` flag. When enabled, Ghostunnel will limit its access to files and sockets based on the flags passed at startup. Note that this functionality is still experimental, and does not work with PKCS#11 modules. +Ghostunnel can use [Landlock](https://landlock.io) to limit process privileges on Linux. Landlock is enabled by default (in best-effort mode) on v1.9.0 or later. On Ghostunnel v1.8.x, Landlock can enabled using the `--use-landlock` flag. When enabled, Ghostunnel will limit its access to files and sockets based on the flags passed at startup. Note that Landlock does not work with PKCS#11 modules and is disabled if PKCS#11 is used (as PKCS#11 modules are opaque to us we can't craft workable Landlock rules for them). diff --git a/landlock_linux.go b/landlock_linux.go index 22543d3fdb..cbe9c18b6e 100644 --- a/landlock_linux.go +++ b/landlock_linux.go @@ -20,7 +20,7 @@ package main import ( "errors" - "log" + "fmt" "net" "net/url" "os" @@ -46,7 +46,7 @@ func addLandlockTestPaths(paths []string) { // setupLandlock processes flags given to the process and generates an // appropriate landlock rule configuration to limit our privileges. -func setupLandlock(logger *log.Logger) error { +func setupLandlock() error { fsRules := []landlock.Rule{} fsRules = append(fsRules, testRules...) @@ -90,7 +90,7 @@ func setupLandlock(logger *log.Logger) error { rule, err := ruleFromStringAddress(*addr, landlock.BindTCP) if err != nil { - logger.Printf("error processing argument '%s' for landlock rule", *addr) + return fmt.Errorf("error processing argument '%s' for landlock rule: %v", *addr, err) } if rule != nil { netRules = append(netRules, rule) @@ -110,7 +110,7 @@ func setupLandlock(logger *log.Logger) error { rule, err := ruleFromStringAddress(*addr, landlock.ConnectTCP) if err != nil { - logger.Printf("error processing argument '%s' for landlock rule", *addr) + return fmt.Errorf("error processing argument '%s' for landlock rule: %v", *addr, err) } if rule != nil { netRules = append(netRules, rule) @@ -156,7 +156,7 @@ func setupLandlock(logger *log.Logger) error { rule, err := ruleFromTCPAddress(*addr, landlock.ConnectTCP) if err != nil { - logger.Printf("error processing argument '%s' for landlock rule", *addr) + return fmt.Errorf("error processing argument '%s' for landlock rule: %v", *addr, err) } if rule != nil { netRules = append(netRules, rule) @@ -171,7 +171,7 @@ func setupLandlock(logger *log.Logger) error { rule, err := ruleFromURL(*url, landlock.ConnectTCP) if err != nil { - logger.Printf("error processing argument '%s' for landlock rule", *url) + return fmt.Errorf("error processing argument '%s' for landlock rule: %v", *url, err) } if rule != nil { netRules = append(netRules, rule) @@ -185,14 +185,9 @@ func setupLandlock(logger *log.Logger) error { config := landlock.V4 err := config.RestrictPaths(fsRules...) if err != nil { - logger.Printf("warning: unable to set up landlock filesystem rules: %v", err) return err } - err = config.RestrictNet(netRules...) - if err != nil { - logger.Printf("warning: unable to set up landlock network rules: %v", err) - } - return err + return config.RestrictNet(netRules...) } func ruleFromStringAddress(addr string, ruleFromPort portRuleFunc) (landlock.Rule, error) { diff --git a/landlock_other.go b/landlock_other.go index 2abd558258..34f4e095f3 100644 --- a/landlock_other.go +++ b/landlock_other.go @@ -18,10 +18,8 @@ package main -import "log" - func addLandlockTestPaths(paths []string) {} -func setupLandlock(logger *log.Logger) error { +func setupLandlock() error { return nil } diff --git a/main.go b/main.go index 4b93e7105b..5a87d15328 100644 --- a/main.go +++ b/main.go @@ -64,7 +64,7 @@ var ( pkcs11Module *string //nolint:golint,unused pkcs11TokenLabel *string //nolint:golint,unused pkcs11PIN *string //nolint:golint,unused - useLandlock *bool //nolint:golint,unused + disableLandlock *bool //nolint:golint,unused ) // Main flags (always supported) @@ -170,7 +170,11 @@ func init() { } if runtime.GOOS == "linux" { - useLandlock = app.Flag("use-landlock", "If true, will use landlock to limit file and socket access on supported kernels.").Bool() + // Deprecated flag: Landlock is now enabled by default. + app.Flag("use-landlock", "").Hidden().Bool() + + // Flag to disable use of landlock if necessary. Note that landlock is automatically disabled when PKCS#11 is used. + disableLandlock = app.Flag("disable-landlock", "Disable the best-effort landlock sandboxing.").Bool() } // Aliases for flags that were renamed to be backwards-compatible @@ -250,9 +254,6 @@ func validateFlags(app *kingpin.Application) error { if *connectTimeout == 0 { return fmt.Errorf("--connect-timeout duration must not be zero") } - if pkcs11Module != nil && *pkcs11Module != "" && useLandlock != nil && *useLandlock { - return fmt.Errorf("--use-landlock is not compatible with --pkcs11-module") - } return nil } @@ -434,14 +435,23 @@ func run(args []string) error { logger.Printf("starting ghostunnel in %s mode", command) // Landlock - if useLandlock != nil && *useLandlock { + hasPKCS11 := pkcs11Module != nil && *pkcs11Module != "" + hasLandlock := runtime.GOOS == "linux" && !*disableLandlock + + if hasPKCS11 && hasLandlock { + logger.Printf("note: using pkcs11, skipping landlock setup (landlock is not compatible with pkcs11)") + } + if !hasPKCS11 && hasLandlock { logger.Printf("setting up landlock rules to limit process privileges") - // Ignore landlock errors (for now). Landlock is a relatively new feature - // and not supported on older kernels (net rules were added in v6.7, Jan - // 2024). We may change this in a future version of Ghostunnel as we get - // more comfortable with Landlock. - _ = setupLandlock(logger) + // Continue even if landlock errs out. Landlock is a new-ish feature and + // not supported on older kernels (net rules were added in v6.7, Jan 2024). + // We may change this in a future version of Ghostunnel as we get more + // comfortable with Landlock. + err := setupLandlock() + if err != nil { + logger.Printf("warning: unable to set up landlock: %v", err) + } } // Metrics diff --git a/main_test.go b/main_test.go index 071ce427b1..1c668426a9 100644 --- a/main_test.go +++ b/main_test.go @@ -149,15 +149,6 @@ func TestFlagValidation(t *testing.T) { err = validateFlags(nil) assert.NotNil(t, err, "invalid --connect-timeout should be rejected") *connectTimeout = 10 * time.Second - - isTrue := true - somePath := "/tmp/test" - useLandlock = &isTrue - pkcs11Module = &somePath - err = validateFlags(nil) - assert.NotNil(t, err, "--use-landlock and --pkcs11-module are incompatible") - useLandlock = nil - pkcs11Module = nil } func TestServerFlagValidation(t *testing.T) { diff --git a/tests/common.py b/tests/common.py index da80ea3b27..7ec02a7965 100755 --- a/tests/common.py +++ b/tests/common.py @@ -23,13 +23,6 @@ def run_ghostunnel(args, stdout=sys.stdout.buffer, stderr=sys.stderr.buffer, pre if not any('close-timeout' in f for f in args): args.append('--close-timeout=1s') - # Enable landlock in integration tests, unless we're using PKCS11 modules. - # Because PKCS11 modules are arbitrary SO files they can do anything at - # runtime, and we can't guarantee that our landlock rules will work for - # them. - if not any('pkcs11-module' in f for f in args) and platform.system() == "Linux": - args.append('--use-landlock') - # Pass args through env var into integration test hook env = os.environ.copy() env["SYSTEMD_LOG_TARGET"] = "console" From db2f6321fe9204250b4782ffcb2e7c3848d2be7a Mon Sep 17 00:00:00 2001 From: Cedric Staub Date: Sat, 29 Nov 2025 20:42:01 -0800 Subject: [PATCH 2/6] Add debug output for status tests --- status_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/status_test.go b/status_test.go index bf587da836..600c984386 100644 --- a/status_test.go +++ b/status_test.go @@ -220,7 +220,7 @@ func TestStatusTargetHTTP2XX(t *testing.T) { statusResp, statusRespCode := statusTargetWithResponseStatusCode(200) if !statusResp.Ok || statusResp.BackendStatus != "ok" || statusRespCode != 200 { - t.Error("status should return 200 when status backend returns 200") + t.Error("status should return 200 when status backend returns 200, but got:", statusResp, statusRespCode) } } @@ -228,7 +228,7 @@ func TestStatusTargetHTTPNon2XX(t *testing.T) { statusResp, statusRespCode := statusTargetWithResponseStatusCode(503) if statusResp.Ok || statusResp.BackendStatus == "ok" || statusRespCode != 503 { - t.Error("status should return 503 when status backend returns something other than 200") + t.Error("status should return 503 when status backend returns something other than 200, but got:", statusResp, statusRespCode) } } @@ -236,7 +236,7 @@ func TestStatusTargetHTTPWithError(t *testing.T) { statusResp, statusRespCode := statusTargetWithResponseStatusCode(-1) if statusResp.Ok || statusResp.BackendStatus == "ok" || statusRespCode != 503 { - t.Error("status should return 503 when status backend returns something other than 200") + t.Error("status should return 503 when status backend returns something other than 200, but got:", statusResp, statusRespCode) } } @@ -262,7 +262,10 @@ func statusTargetWithResponseStatusCode(code int) (statusResponse, int) { res := response.Result() defer res.Body.Close() - data, _ := io.ReadAll(res.Body) + data, err := io.ReadAll(res.Body) + if err != nil { + panic(err) + } statusResp := statusResponse{} _ = json.Unmarshal(data, &statusResp) From 114eba3e63a40052297656f18b1cbcf6ed555c36 Mon Sep 17 00:00:00 2001 From: Cedric Staub Date: Sat, 29 Nov 2025 20:54:30 -0800 Subject: [PATCH 3/6] Disable landlock in TestInvalidCABundle unit test --- main.go | 1 + main_test.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 5a87d15328..79f39fecb9 100644 --- a/main.go +++ b/main.go @@ -462,6 +462,7 @@ func run(args []string) error { if *metricsURL != "" { logger.Printf("metrics enabled; reporting metrics via POST to %s", *metricsURL) } + // Always enable prometheus registry. The overhead should be quite minimal as an in-mem map is updated // with the values. pClient := prometheusmetrics.NewPrometheusProvider(metrics.DefaultRegistry, *metricsPrefix, "", prometheus.DefaultRegisterer, 1*time.Second) diff --git a/main_test.go b/main_test.go index 1c668426a9..ae297e59a5 100644 --- a/main_test.go +++ b/main_test.go @@ -23,6 +23,7 @@ import ( "os" "path" "path/filepath" + "runtime" "sync" "testing" "time" @@ -366,13 +367,18 @@ func TestServerBackendDialerError(t *testing.T) { } func TestInvalidCABundle(t *testing.T) { - err := run([]string{ + cmd := []string{ "server", "--cacert", "/dev/null", "--target", "localhost:8080", "--keystore", "keystore.p12", "--listen", "localhost:8080", - }) + } + if runtime.GOOS == "linux" { + // Disable landlock so we don't inadvertendly affect later unit tests. + cmd = append(cmd, "--disable-landlock") + } + err := run(cmd) assert.NotNil(t, err, "invalid CA bundle should exit with error") } From 6005c4844c28fdb4a92a8b9b046391871b44ecbf Mon Sep 17 00:00:00 2001 From: Cedric Staub Date: Sat, 29 Nov 2025 21:10:34 -0800 Subject: [PATCH 4/6] Bump versions of Github actions (checkout, setup-go/python, download/upload-artifact) --- .github/workflows/compile.yml | 26 +++++++++++++------------- .github/workflows/docker.yml | 2 +- .github/workflows/lint.yml | 4 ++-- .github/workflows/release.yml | 34 +++++++++++++++++----------------- .github/workflows/test.yml | 12 ++++++------ 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index f7ee1e87e9..0b82713911 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Set up buildx command @@ -39,12 +39,12 @@ jobs: sudo apt-get update sudo apt-get install -y gcc-aarch64-linux-gnu - name: Set up toolchain - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 100 fetch-tags: true @@ -56,12 +56,12 @@ jobs: CGO_ENABLED=1 GOARCH=arm64 CC=aarch64-linux-gnu-gcc make ghostunnel mv ghostunnel ghostunnel-linux-arm64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-linux-amd64-${{ matrix.os }} path: ghostunnel-linux-amd64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-linux-arm64-${{ matrix.os }} path: ghostunnel-linux-arm64 @@ -74,12 +74,12 @@ jobs: runs-on: macos-latest steps: - name: Set up toolchain - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 100 fetch-tags: true @@ -92,17 +92,17 @@ jobs: mv ghostunnel ghostunnel-darwin-arm64 lipo -create -output ghostunnel-darwin-universal ghostunnel-darwin-amd64 ghostunnel-darwin-arm64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-darwin-amd64 path: ghostunnel-darwin-amd64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-darwin-arm64 path: ghostunnel-darwin-arm64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-darwin-universal path: ghostunnel-darwin-universal @@ -115,19 +115,19 @@ jobs: runs-on: windows-latest steps: - name: Set up toolchain - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 100 fetch-tags: true - name: Build binary run: make ghostunnel - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-windows-amd64 path: ghostunnel diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e0e67f6168..b16f5bbdb2 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Set up emulation diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7c628d382d..000ce46883 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,8 +14,8 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Checkout - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + uses: actions/checkout@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} - name: golangci-lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6ab8ccb920..a553ac7427 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,12 +18,12 @@ jobs: sudo apt-get update sudo apt-get install -y gcc-aarch64-linux-gnu - name: Set up toolchain - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Build binary @@ -34,12 +34,12 @@ jobs: CGO_ENABLED=1 GOARCH=arm64 CC=aarch64-linux-gnu-gcc make VERSION=$GITHUB_REF_NAME ghostunnel mv ghostunnel ghostunnel-linux-arm64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-linux-amd64 path: ghostunnel-linux-amd64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-linux-arm64 path: ghostunnel-linux-arm64 @@ -52,12 +52,12 @@ jobs: runs-on: macos-latest steps: - name: Set up toolchain - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Build binary @@ -69,17 +69,17 @@ jobs: mv ghostunnel ghostunnel-darwin-arm64 lipo -create -output ghostunnel-darwin-universal ghostunnel-darwin-amd64 ghostunnel-darwin-arm64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-darwin-amd64 path: ghostunnel-darwin-amd64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-darwin-arm64 path: ghostunnel-darwin-arm64 - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-darwin-universal path: ghostunnel-darwin-universal @@ -92,12 +92,12 @@ jobs: runs-on: windows-latest steps: - name: Set up toolchain - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Build binary @@ -105,7 +105,7 @@ jobs: make VERSION=$GITHUB_REF_NAME ghostunnel mv ghostunnel ghostunnel-windows-amd64.exe - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: ghostunnel-windows-amd64.exe path: ghostunnel-windows-amd64.exe @@ -118,7 +118,7 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Create release @@ -147,11 +147,11 @@ jobs: - { os: 'darwin', arch: 'universal' } steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Download artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v6 with: name: ghostunnel-${{ matrix.target.os }}-${{ matrix.target.arch }} path: dist @@ -175,11 +175,11 @@ jobs: - { os: 'windows', arch: 'amd64' } steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Download artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v6 with: name: ghostunnel-${{ matrix.target.os }}-${{ matrix.target.arch }}.exe path: dist diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d42c0742d4..8cd54796ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,12 +17,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Build binary run: make ghostunnel - name: Run tests @@ -37,7 +37,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Run tests run: GO_VERSION=${{ matrix.version }} make docker-test - name: Codecov upload @@ -61,18 +61,18 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.version }} id: go - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.11.x' - name: Install gocovmerge run: go install github.com/wadey/gocovmerge@latest - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Run tests run: make test - name: Codecov upload From 806c3d8bf581b477327ed21f986f7c959fdf7018 Mon Sep 17 00:00:00 2001 From: Cedric Staub Date: Sat, 29 Nov 2025 21:27:31 -0800 Subject: [PATCH 5/6] Add flag to skip DNS resolution on startup, fixes #585 --- main.go | 11 ++++++----- socket/net.go | 5 +---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/main.go b/main.go index 79f39fecb9..a1e3e0f585 100644 --- a/main.go +++ b/main.go @@ -138,11 +138,12 @@ var ( metricsPrefix = app.Flag("metrics-prefix", fmt.Sprintf("Set prefix string for all reported metrics (default: %s).", defaultMetricsPrefix)).PlaceHolder("PREFIX").Default(defaultMetricsPrefix).String() metricsInterval = app.Flag("metrics-interval", "Collect (and post/send) metrics every specified interval.").Default("30s").Duration() - // Status & logging + // Status, logging & other statusAddress = app.Flag("status", "Enable serving /_status and /_metrics on given HOST:PORT (or unix:SOCKET).").PlaceHolder("ADDR").String() enableProf = app.Flag("enable-pprof", "Enable serving /debug/pprof endpoints alongside /_status (for profiling).").Bool() enableShutdown = app.Flag("enable-shutdown", "Enable serving a /_shutdown endpoint alongside /_status to allow terminating via HTTP.").Default("false").Bool() quiet = app.Flag("quiet", "Silence log messages (can be all, conns, conn-errs, handshake-errs; repeat flag for more than one)").Default("").Enums("", "all", "conns", "handshake-errs", "conn-errs") + skipResolve = app.Flag("skip-resolve", "Skip resolving target host on startup (useful to start Ghostunnel before network is up).").Default("false").Bool() // Man page /help _ = app.Flag("help-custom-man", "Generate a man page.").Hidden().PreAction(generateManPage).Bool() @@ -541,8 +542,8 @@ func run(args []string) error { // on our side if the connection is forwarded through a CONNECT proxy. Hence, // we ignore "no such host" errors when a proxy is set and trust that the // proxy will be able to find the target for us. - skipResolve := *clientProxy != nil - network, address, host, err := socket.ParseAddress(*clientForwardAddress, skipResolve) + skipRes := *skipResolve || *clientProxy != nil + network, address, host, err := socket.ParseAddress(*clientForwardAddress, skipRes) if err != nil { logger.Printf("error: invalid target address: %s\n", err) return err @@ -760,7 +761,7 @@ func (env *Environment) serveStatus() error { https, addr := socket.ParseHTTPAddress(*statusAddress) - network, address, _, err := socket.ParseAddress(addr, false) + network, address, _, err := socket.ParseAddress(addr, true) if err != nil { return err } @@ -800,7 +801,7 @@ func (env *Environment) serveStatus() error { // Get backend dialer function in server mode (connecting to a unix socket or tcp port) func serverBackendDialer() (proxy.DialFunc, error) { - backendNet, backendAddr, _, err := socket.ParseAddress(*serverForwardAddress, false) + backendNet, backendAddr, _, err := socket.ParseAddress(*serverForwardAddress, *skipResolve) if err != nil { return nil, err } diff --git a/socket/net.go b/socket/net.go index f23622c86c..94a3d22455 100644 --- a/socket/net.go +++ b/socket/net.go @@ -52,15 +52,12 @@ func ParseAddress(input string, skipResolve bool) (network, address, host string return } + network, address = "tcp", input if !skipResolve { // Make sure target address resolves, unless requested otherwise. _, err = net.ResolveTCPAddr("tcp", input) - if err != nil { - return - } } - network, address = "tcp", input return } From 7eea785915bfc2ff4e4e43cd085f27416c77bf5b Mon Sep 17 00:00:00 2001 From: Cedric Staub Date: Sat, 29 Nov 2025 21:57:25 -0800 Subject: [PATCH 6/6] Build on Go 1.25 --- .github/workflows/compile.yml | 6 +++--- .github/workflows/lint.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/test.yml | 6 +++--- Dockerfile-alpine | 2 +- Dockerfile-debian | 2 +- Dockerfile-test | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 0b82713911..95d1c72b67 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -30,7 +30,7 @@ jobs: name: Build (Linux) strategy: matrix: - version: [1.24.x] + version: [1.25.x] os: [ubuntu-22.04, ubuntu-24.04] runs-on: ${{ matrix.os }} steps: @@ -70,7 +70,7 @@ jobs: name: Build (MacOS) strategy: matrix: - version: [1.24.x] + version: [1.25.x] runs-on: macos-latest steps: - name: Set up toolchain @@ -111,7 +111,7 @@ jobs: name: Build (Windows) strategy: matrix: - version: [1.24.x] + version: [1.25.x] runs-on: windows-latest steps: - name: Set up toolchain diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 000ce46883..5eeedfc260 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,7 +10,7 @@ jobs: name: Lint strategy: matrix: - version: [1.24.x] + version: [1.25.x] runs-on: ubuntu-24.04 steps: - name: Checkout diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a553ac7427..7a4368f77b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: name: Build (Linux) strategy: matrix: - version: [1.24.x] + version: [1.25.x] runs-on: ubuntu-22.04 steps: - name: Set up cross toolchain @@ -48,7 +48,7 @@ jobs: name: Build (MacOS) strategy: matrix: - version: [1.24.x] + version: [1.25.x] runs-on: macos-latest steps: - name: Set up toolchain @@ -88,7 +88,7 @@ jobs: name: Build (Windows) strategy: matrix: - version: [1.24.x] + version: [1.25.x] runs-on: windows-latest steps: - name: Set up toolchain diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8cd54796ee..1c0b45af9d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: name: Unit tests strategy: matrix: - version: [1.24.x] + version: [1.25.x] os: [ubuntu-22.04, ubuntu-24.04, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: @@ -32,7 +32,7 @@ jobs: name: Integration tests (Linux) strategy: matrix: - version: [1.24] + version: [1.25] os: [ubuntu-22.04, ubuntu-24.04] runs-on: ${{ matrix.os }} steps: @@ -56,7 +56,7 @@ jobs: name: Integration tests (Darwin) strategy: matrix: - version: [1.24.x] + version: [1.25.x] os: [macos-latest] runs-on: ${{ matrix.os }} steps: diff --git a/Dockerfile-alpine b/Dockerfile-alpine index 28b0e27d3c..551c93cbdb 100644 --- a/Dockerfile-alpine +++ b/Dockerfile-alpine @@ -6,7 +6,7 @@ # To run ghostunnel from the image (for example): # docker run --rm ghostunnel/ghostunnel --version -FROM golang:1.24-alpine AS build +FROM golang:1.25-alpine AS build # Dependencies RUN apk add --no-cache --update gcc musl-dev libtool make git diff --git a/Dockerfile-debian b/Dockerfile-debian index 99b38e559e..5bf728a2ed 100644 --- a/Dockerfile-debian +++ b/Dockerfile-debian @@ -6,7 +6,7 @@ # To run ghostunnel from the image (for example): # docker run --rm ghostunnel/ghostunnel --version -FROM golang:1.24-bookworm AS build +FROM golang:1.25-bookworm AS build # Dependencies RUN apt update && apt install -y gcc libtool make git diff --git a/Dockerfile-test b/Dockerfile-test index 612473e1e0..2fd890eb70 100644 --- a/Dockerfile-test +++ b/Dockerfile-test @@ -6,7 +6,7 @@ # Run integration tests: # docker run -v /dev/log:/dev/log -v $PWD:/go/src/github.com/ghostunnel/ghostunnel ghostunnel/ghostunnel-test -ARG GO_VERSION="1.24" +ARG GO_VERSION="1.25" FROM golang:${GO_VERSION}