wiresocks

package module
v0.0.0-...-a96360b Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2025 License: MIT Imports: 25 Imported by: 1

README ΒΆ

πŸ”Œ wiresocks

MIT licensed Go Report Card Go Reference

A user-space WireGuard client that exposes a SOCKS and HTTP proxy.

wiresocks allows you to connect to a WireGuard peer and route traffic from any application through the tunnel by connecting to the local proxy server. It runs entirely in user-space, meaning it does not require elevated privileges to operate.

Table of Contents

πŸ’‘ Motivation

Many WireGuard clients require kernel-level access or route all system traffic through the tunnel by default. wiresocks was created to provide a more flexible, lightweight alternative that:

  • Runs without root: Operates entirely in user-space, enhancing security and simplifying setup.
  • Offers per-application tunneling: By exposing a proxy, it allows you to selectively route traffic from specific applications (like web browsers or torrent clients) without affecting the rest of your system.
  • Is simple and portable: As a single, cross-platform binary, it is easy to deploy and run anywhere.

✨ Features

  • User-Space WireGuard: Connects to a WireGuard peer without needing kernel modules or root access.
  • SOCKS and HTTP Proxy: Exposes both SOCKS and HTTP proxies to tunnel application traffic, with optional authentication.
  • Full SOCKS Support: Implements SOCKS5 with TCP (CONNECT) and UDP (ASSOCIATE) support.
  • Standard Configuration: Uses a standard wg-quick-style configuration file.
  • Cross-Platform: Written in Go, it can be built for Linux, macOS, Windows, and more.

πŸš€ Installation

There are multiple ways to install wiresocks.

To install the latest version, use go install:

go install github.com/shahradelahi/wiresocks/cmd/wiresocks@latest
From GitHub Releases

You can download pre-compiled binaries for various operating systems and architectures from the GitHub Releases page.

Building from Source

Clone the repository and use the Makefile to build the binary.

git clone https://github.com/shahradelahi/wiresocks.git
cd wiresocks
make wiresocks

The compiled binary will be located in the build/ directory.

βš™οΈ Usage

Run wiresocks from the command line, providing the path to your WireGuard configuration file.

./build/wiresocks -c ./config.conf
Command-line Flags
  • -c, --config <path>: Path to the WireGuard configuration file (default: ./config.conf).
  • --socks-addr <addr:port>: SOCKS5 proxy bind address.
  • --http-addr <addr:port>: HTTP proxy bind address.
  • -p, --password <password>: Proxy password for authentication (optional).
  • -u, --username <username>: Proxy username for authentication (optional).
  • --silent: Enable silent mode.
  • -v, --version: Show version information and exit.

Example: Run with a SOCKS proxy on port 1080 and an HTTP proxy on port 8118.

./build/wiresocks -c /etc/wireguard/wg0.conf --socks-addr 127.0.0.1:1080 --http-addr 127.0.0.1:8118

πŸ“š Usage as a Library

wiresocks can also be used as a library in your Go projects to embed WireGuard proxy functionality directly into your applications.

Installation

To add wiresocks to your Go project, use go get:

go get github.com/shahradelahi/wiresocks
Example Usage

Here's a basic example of how to start a wiresocks instance programmatically:

package main

import (
	"context"
	"log"
	"net/netip"
	"time"

	"github.com/shahradelahi/wiresocks"
)

func main() {
	// Define WireGuard interface configuration
	iface := wiresocks.InterfaceConfig{
		PrivateKey: "YOUR_PRIVATE_KEY_HEX", // Replace with your actual private key
		Addresses: []netip.Prefix{
			netip.MustParsePrefix("10.0.0.2/32"),
		},
		DNS: []netip.Addr{
			netip.MustParseAddr("1.1.1.1"),
		},
		MTU: 1420,
	}

	// Define WireGuard peer configuration
	peer := wiresocks.PeerConfig{
		PublicKey: "PEER_PUBLIC_KEY_HEX",    // Replace with your peer's public key
		Endpoint:  "peer.example.com:51820", // Replace with your peer's endpoint
		AllowedIPs: []netip.Prefix{
			netip.MustParsePrefix("0.0.0.0/0"),
			netip.MustParsePrefix("::/0"),
		},
		PersistentKeepalive: 25,
	}

	// Define proxy configuration
	socksAddr := netip.MustParseAddrPort("127.0.0.1:1080")
	httpAddr := netip.MustParseAddrPort("127.0.0.1:8118")
	proxyOpts := &wiresocks.ProxyConfig{
		SocksBindAddr: &socksAddr,
		HttpBindAddr:  &httpAddr,
		Username:      "myuser",
		Password:      "mypassword",
	}

	// Create a new WireSocks instance
	ws, err := wiresocks.NewWireSocks(
		wiresocks.WithContext(context.Background()),
		wiresocks.WithWireguardConfig(&wiresocks.Configuration{
			Interface: &iface,
			Peers:     []wiresocks.PeerConfig{peer},
		}),
		wiresocks.WithProxyConfig(proxyOpts),
		wiresocks.WithLogLevel(wiresocks.LogLevelVerbose),
		wiresocks.WithConnectivityTest(&wiresocks.ConnectivityTestOptions{
			Enabled: true,
			URL:     "https://1.1.1.1/cdn-cgi/trace/",
			Timeout: 10 * time.Second,
		}),
	)
	if err != nil {
		log.Fatalf("Failed to create WireSocks instance: %v", err)
	}

	// Run WireSocks in a goroutine
	go func() {
		if err := ws.Run(); err != nil {
			log.Fatalf("WireSocks failed to run: %v", err)
		}
	}()

	// Keep the main goroutine alive until interrupted
	select {
	case <-context.Background().Done():
		// Handle shutdown gracefully
	}
}

🐳 Docker

You can also run wiresocks using Docker.

Building the Image

Build the Docker image using the provided Dockerfile:

docker build -t wiresocks .
Running the Container

When running the container, you must mount your configuration file and expose the necessary ports.

docker run -d \
  --name wiresocks \
  -v /path/to/your/config.conf:/etc/wiresocks/config.conf:ro \
  -p 1080:1080 \
  --restart=unless-stopped \
  wiresocks

This command runs wiresocks in the background, mounts your local config.conf as read-only, and exposes the SOCKS proxy on port 1080.

To use an HTTP proxy, add the -h flag and expose its port:

docker run -d \
  --name wiresocks \
  -v /path/to/your/config.conf:/etc/wiresocks/config.conf:ro \
  -p 1080:1080 \
  -p 8118:8118 \
  --restart=unless-stopped \
  wiresocks -h 0.0.0.0:8118

Note: Inside the container, the proxy must bind to 0.0.0.0 to be accessible from outside.

πŸ“ Configuration

wiresocks uses a configuration file format that is compatible with wg-quick.

The file must contain one [Interface] section and at least one [Peer] section.

Example config.conf:

[Interface]
# The private key for the client (this machine)
PrivateKey = <your-private-key>

# (Optional) IP addresses to assign to the interface
Address = 10.0.0.2/32

# (Optional) DNS servers to use for resolution
DNS = 1.1.1.1

# (Optional) MTU for the interface
MTU = 1420

[Peer]
# The public key of the WireGuard peer (the server)
PublicKey = <peer-public-key>

# (Optional) A pre-shared key for an extra layer of security
PresharedKey = <your-preshared-key>

# A comma-separated list of IPs to be routed through the tunnel
AllowedIPs = 0.0.0.0/0, ::/0

# The public endpoint of the WireGuard peer
Endpoint = <peer-ip-or-hostname>:<peer-port>

# (Optional) Keepalive interval in seconds
PersistentKeepalive = 25

🀝 Contributing

Want to contribute? Awesome! To show your support is to star the project, or to raise issues on GitHub

Thanks again for your support, it is much appreciated! πŸ™

License

MIT Β© Shahrad Elahi

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

View Source
const (
	LogLevelSilent = iota
	LogLevelError
	LogLevelVerbose
)

Log levels for use with NewLogger.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func DiscardLogf ΒΆ

func DiscardLogf(format string, args ...any)

DiscardLogf Function for use in Logger for discarding logged lines.

func EncodeBase64ToHex ΒΆ

func EncodeBase64ToHex(key string) (string, error)

func EncodeHexToBase64 ΒΆ

func EncodeHexToBase64(key string) (string, error)

func MustParsePrefixOrAddr ΒΆ

func MustParsePrefixOrAddr(s string) netip.Prefix

MustParsePrefixOrAddr parses s as a netip.Prefix. If that fails, it parses s as a netip.Addr and returns it as a full-prefix. It panics if parsing as an address fails.

func ParsePrefixOrAddr ΒΆ

func ParsePrefixOrAddr(s string) (netip.Prefix, error)

ParsePrefixOrAddr parses s as a netip.Prefix. If that fails, it parses s as a netip.Addr and returns it as a full-prefix.

func ParseResolveAddressPort ΒΆ

func ParseResolveAddressPort(hostname string, includev6 bool, dnsServer string) (netip.AddrPort, error)

func RandomIPFromPrefix ΒΆ

func RandomIPFromPrefix(cidr netip.Prefix) (netip.Addr, error)

RandomIPFromPrefix returns a random IP from the provided CIDR prefix. Supports IPv4 and IPv6. Does not support mapped inputs.

Types ΒΆ

type Configuration ΒΆ

type Configuration struct {
	Interface *InterfaceConfig
	Peers     []PeerConfig
}

func ParseConfig ΒΆ

func ParseConfig(path string) (*Configuration, error)

ParseConfig takes the path of a configuration file and parses it into Configuration

func ParseConfigFromText ΒΆ

func ParseConfigFromText(configText string) (*Configuration, error)

ParseConfigFromText takes configuration text directly and parses it into Configuration

func (*Configuration) String ΒΆ

func (c *Configuration) String() (string, error)

type ConnectivityTestOptions ΒΆ

type ConnectivityTestOptions struct {
	Enabled bool
	URL     string
	Timeout time.Duration
}

ConnectivityTestOptions holds the configuration for the connectivity test.

type InterfaceConfig ΒΆ

type InterfaceConfig struct {
	PrivateKey string
	Addresses  []netip.Prefix
	DNS        []netip.Addr
	MTU        int
	FwMark     uint32
}

func ParseInterface ΒΆ

func ParseInterface(cfg *ini.File) (InterfaceConfig, error)

ParseInterface parses the [Interface] section

type Logger ΒΆ

type Logger struct {
	LogLevel int
	Verbosef func(format string, args ...any)
	Errorf   func(format string, args ...any)
}

A Logger provides logging for a Device. The functions are Printf-style functions. They must be safe for concurrent use. They do not require a trailing newline in the format. If nil, that level of logging will be silent.

func NewLogger ΒΆ

func NewLogger(level int) *Logger

NewLogger constructs a Logger that writes to stdout. It logs at the specified log level and above. It decorates log lines with the log level, date, time, and prepend.

type Option ΒΆ

type Option func(*WireSocks)

func WithConnectivityTest ΒΆ

func WithConnectivityTest(opts *ConnectivityTestOptions) Option

func WithContext ΒΆ

func WithContext(ctx context.Context) Option

func WithLogLevel ΒΆ

func WithLogLevel(loglevel int) Option

func WithPeer ΒΆ

func WithPeer(peer PeerConfig) Option

func WithPrivateKey ΒΆ

func WithPrivateKey(key string) Option

func WithProxyConfig ΒΆ

func WithProxyConfig(opts *ProxyConfig) Option

func WithWireguardConfig ΒΆ

func WithWireguardConfig(conf *Configuration) Option

type PeerConfig ΒΆ

type PeerConfig struct {
	PublicKey    string
	PreSharedKey string
	Endpoint     string
	KeepAlive    int
	AllowedIPs   []netip.Prefix
}

func ParsePeers ΒΆ

func ParsePeers(cfg *ini.File) ([]PeerConfig, error)

ParsePeers parses the [Peer] section and extract the information into `peers`

type ProxyConfig ΒΆ

type ProxyConfig struct {
	SocksBindAddr *netip.AddrPort
	HttpBindAddr  *netip.AddrPort
	Username      string
	Password      string
}

ProxyConfig holds the configuration for the proxies.

type VirtualTun ΒΆ

type VirtualTun struct {
	Tnet *netstack.Net
	Dev  *device.Device
	// contains filtered or unexported fields
}

VirtualTun stores a reference to netstack network

func (VirtualTun) CheckConnectivity ΒΆ

func (vt VirtualTun) CheckConnectivity(ctx context.Context, url string, timeout time.Duration) error

func (VirtualTun) LookupAddr ΒΆ

func (vt VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, error)

LookupAddr lookups a hostname. DNS traffic may or may not be routed depending on VirtualTun's setting

func (VirtualTun) Resolve ΒΆ

func (vt VirtualTun) Resolve(ctx context.Context, name string) (context.Context, net.IP, error)

Resolve resolves a hostname and returns an IP. DNS traffic may or may not be routed depending on VirtualTun's setting

func (VirtualTun) ResolveAddrWithContext ΒΆ

func (vt VirtualTun) ResolveAddrWithContext(ctx context.Context, name string) (*netip.Addr, error)

ResolveAddrWithContext resolves a hostname and returns an AddrPort. DNS traffic may or may not be routed depending on VirtualTun's setting

func (VirtualTun) Stop ΒΆ

func (vt VirtualTun) Stop()

type WireSocks ΒΆ

type WireSocks struct {
	// contains filtered or unexported fields
}

func NewWireSocks ΒΆ

func NewWireSocks(options ...Option) (*WireSocks, error)

func (*WireSocks) Run ΒΆ

func (s *WireSocks) Run() error

func (*WireSocks) Stop ΒΆ

func (s *WireSocks) Stop()

Directories ΒΆ

Path Synopsis
cmd
wiresocks command
internal
proxy

Jump to

Keyboard shortcuts

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