tuncat

module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2026 License: MIT

README

tuncat

Universal tunnel managment utility in pure Go. Inspired by netcat and rclone.

tuncat is a Go VPN client for Cisco AnyConnect-compatible gateways. It embeds the VPN core in-process and keeps the legacy CLI/config contract intact.

What stays the same

  • same CLI flags (-server, -username, -password, -pfx-path, -pfx-password, -base-mtu, -config, -verbose)
  • same YAML fields (server, username, password, pfx_path, pfx_password, base_mtu, split_routes, dns_domains, etc.)
  • same tuncat obscure workflow for secret values
  • cert + password auth is mandatory

When a config file contains plaintext password or pfx_password, tuncat now rewrites them to obscured:... automatically after a successful connection. CLI-provided secrets are not written back.

Runtime Notes

  • Linux: root privileges and /dev/net/tun
  • macOS: administrator privileges to configure the tunnel, routes, and DNS Known exception: interface address setup still invokes the system ifconfig binary.
  • Windows: Administrator privileges to configure the tunnel, routes, and DNS

No external openconnect or openssl runtime binaries are required.

Quick Start

By default, tuncat searches config in this order:

  • ./tuncat/config.yaml
  • ./.tuncat/config.yaml
  • ./config.yaml (legacy fallback)
  • ~/tuncat/config.yaml
  • ~/.tuncat/config.yaml

Create ./tuncat/config.yaml (same schema as before):

server: "vpn.example.com/external"
username: "<USERNAME>"
password: "obscured:<HASH>"
pfx_path: "denys.dudko.pfx"
pfx_password: "obscured:<HASH>"
base_mtu: 1200

split_routes:
  - "10.0.0.0/8"

dns_domains:
  - "example.internal"
  - "group.example.internal"
  - "external.example.internal"

verify_url: "https://intranet.example.internal/health"

Generate obscured values:

tuncat obscure

Connect:

sudo tuncat -config ./tuncat/config.yaml

Disconnect with Ctrl+C.

Usage

$ tuncat --help

Usage of tuncat:
  -base-mtu int
        base MTU value
  -config string
        path to config file
  -password string
        login password
  -pfx-password string
        password for .pfx file
  -pfx-path string
        path to .pfx certificate file
  -server string
        VPN server address
  -username string
        login username
  -verbose
        enable verbose VPN core logs
  -version
        show version

Config Example

See config.example.yml.

Legacy fields are still accepted:

  • protocol
  • user_agent
  • server_cert
  • openconnect_path (kept for compatibility; ignored by embedded runtime)

verify_url is optional. When set, tuncat performs a post-connect DNS lookup and HTTP probe and logs the structured result. Probe failure is treated as a failed connection attempt.

Development

Install the pinned local toolchain with aqua:

aqua i

This installs the repo-pinned Go toolchain from go.mod plus:

  • act
  • lefthook
  • gitleaks
  • actionlint
  • golangci-lint

Install local git hooks once per clone:

aqua exec -- lefthook install

The local hooks use the same task surface as CI:

  • pre-commit: formats staged Go files with gofmt and runs act workflow_dispatch -j cross-build
  • pre-push: runs act workflow_dispatch -j lint, act workflow_dispatch -j test, and act workflow_dispatch -j secrets

GitHub Actions is the task surface now. Run jobs locally with act:

act -l
act -j build
act -j test
act -j lint
act -j secrets
act -j cross-build

act requires Docker. The repo-local .actrc provides the default workflow directory and container architecture.

Build artifacts are written to dist/ and named by target platform:

dist/tuncat_linux_amd64
dist/tuncat_linux_arm64
dist/tuncat_darwin_amd64
dist/tuncat_darwin_arm64
dist/tuncat_windows_amd64.exe

For a manual smoke test on a machine with a real local config, run:

sudo ./dist/tuncat_linux_amd64 -config ./config.yml -verbose

If your local file is named config.yaml instead, pass that path instead. When verify_url is configured, this also exercises the post-connect connectivity probe.

For repository secret scans, the secrets job runs gitleaks git ., which avoids false positives from ignored local files such as personal configs or certificates.

Directories

Path Synopsis
cmd
tuncat command
internal
cli
engine/device
Package device copies the interface shape from wireguard-go's tun package.
Package device copies the interface shape from wireguard-go's tun package.
engine/device/rwcancel
Package rwcancel implements cancelable read/write operations on a file descriptor.
Package rwcancel implements cancelable read/write operations on a file descriptor.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL