34 Commits

Author SHA1 Message Date
octeep
bc77be08cc bump version to 1.0.4 2022-08-23 22:04:36 +08:00
octeep
b887606007 add print version flag 2022-08-23 21:43:30 +08:00
octeep
ab4a5212d9 Merge pull request #45 from jordemort/distroless-docker
Redo Dockerfile
2022-08-23 19:51:12 +08:00
octeep
b592741872 Do not push to registry on PRs 2022-08-23 19:40:09 +08:00
octeep
b035e2b7dd Revert "Try publishing to Docker Hub instead"
This reverts commit b2546b3219.
2022-08-23 19:37:37 +08:00
Jordan Webb
b2546b3219 Try publishing to Docker Hub instead 2022-08-21 23:04:34 -05:00
Jordan Webb
9c5b2622af Try moving permissions key to top-level 2022-08-21 09:18:14 -05:00
Jordan Webb
2ac9fad93e Try giving the workflow packages: write 2022-08-21 09:03:58 -05:00
octeep
0b72e1dded Update README.md 2022-08-21 11:09:30 +08:00
octeep
8f05071a81 Merge pull request #47 from jordemort/multiple-peers
Allow multiple peers, tunnels, and proxies
2022-08-21 11:04:52 +08:00
octeep
e102c35f85 update wireguard dependency and fix linter 2022-08-21 10:56:10 +08:00
Jordan Webb
704fc1dbe5 Add metadata to image 2022-08-20 20:04:48 -05:00
Jordan Webb
02a56cad13 Allow multiple peers, tunnels, and proxies 2022-08-20 19:11:40 -05:00
Jordan Webb
d238fef2e9 Add workflow to build container 2022-08-20 09:56:08 -05:00
Jordan Webb
be8865eeb1 Redo Dockerfile
- Build the currently checked-out code, instead of cloning the repo
inside the Dockerfile. This makes it much easier to build a container
for a particular branch or commit; people working on personal forks
will be able to build containers for their forks without modifying the
Dockerfile.

- Switch from Alpine to distroless; I couldn't actually get the current
version of the Dockerfile to build, it kept dying with some error about
gvisor. Aside from building with no trouble, the new Dockerfile reduces
the size of the image from 23MB to 9MB.

- Move Dockerfile into the root; this is a matter of taste, but allows
one to simply `docker build` the directory instead of having to also
specify the path to the Dockerfile. As part of this, I removed the
`config` and `Makefile` from the `docker` directory, since they seemed
specific to someone's setup and incomplete without that context.
2022-08-20 09:55:55 -05:00
octeep
6e3c3a25f3 update go version to 1.18 2022-05-20 12:25:48 +01:00
octeep
afcb393464 Update wireproxy.yml 2022-04-05 07:32:38 +01:00
octeep
f637b0f916 resolve host for every new connection in static tunnels 2022-04-04 20:45:28 +01:00
octeep
06d425be3a fix misspellings in CI 2022-04-04 06:02:47 +01:00
octeep
17b31c5fc7 Merge remote-tracking branch 'refs/remotes/origin/master' 2022-04-04 06:02:15 +01:00
octeep
eee0bfc80a OpenBSD unveil to prevent -d from executing other binaries 2022-04-04 06:00:38 +01:00
octeep
04dd90b25b Update wireproxy.yml 2022-04-03 19:55:16 +01:00
octeep
2b116ffad6 Merge remote-tracking branch 'refs/remotes/origin/master' 2022-04-03 19:42:29 +01:00
octeep
6ab6551686 replace log.Panic with log.Fatal 2022-04-03 19:42:19 +01:00
octeep
6bdeffe3f2 Add IPv6 support 2022-04-03 19:35:08 +01:00
octeep
9224e79eea Update Dockerfile #32 2022-04-03 10:10:35 +01:00
octeep
d1711b02b6 Revert "add freebsd and openbsd to goreleaser"
This reverts commit e38b0155dd.
2022-04-01 01:16:38 +01:00
octeep
2fb865da94 Update README.md 2022-04-01 01:07:50 +01:00
octeep
00cb3dd99e Merge remote-tracking branch 'refs/remotes/origin/master' 2022-04-01 00:47:29 +01:00
octeep
0048d87cad add documentation 2022-04-01 00:47:14 +01:00
octeep
564dfe2c79 Create FUNDING.yml 2022-03-31 23:24:08 +01:00
octeep
f93e047f64 add pledge call on OpenBSD 2022-03-31 20:15:05 +01:00
octeep
863440f936 Trigger gorelease when v* tag is created 2022-03-31 20:14:13 +01:00
octeep
e38b0155dd add freebsd and openbsd to goreleaser 2022-03-31 18:32:34 +01:00
19 changed files with 486 additions and 222 deletions

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
.dockerignore
.github
.gitignore
Dockerfile
LICENSE
README.md

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
liberapay: octeep

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Windows amd64 Version
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o WireProxy_amd64.exe -v ./cmd/wireproxy
@@ -36,7 +36,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Windows arm64 Version
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -o WireProxy_arm64.exe -v ./cmd/wireproxy
@@ -56,7 +56,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Linux amd64 Version
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o WireProxy_amd64 -v ./cmd/wireproxy
@@ -76,7 +76,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Linux arm64 Version
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o WireProxy_arm64 -v ./cmd/wireproxy
@@ -96,7 +96,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Linux s390x Version
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o WireProxy_s390x -v ./cmd/wireproxy
@@ -116,7 +116,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Darwin amd64 Version
run: |
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o WireProxy_amd64 -v ./cmd/wireproxy
@@ -136,7 +136,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Building Darwin arm64 Version
run: |
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o WireProxy_arm64 -v ./cmd/wireproxy

71
.github/workflows/container.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: Build container
on:
push:
branches:
- master
pull_request:
# Allow for manually running
workflow_dispatch:
inputs:
container_tag:
description: Tag for container
default: "latest"
required: true
permissions:
packages: write
jobs:
container:
runs-on: ubuntu-20.04
env:
CONTAINER_NAME: ghcr.io/${{ github.repository }}
BUILD_PLATFORMS: linux/amd64,linux/arm,linux/arm64,linux/ppc64le,linux/s390x
RAW_CONTAINER_TAG: ${{ github.event.inputs.container_tag || github.event.pull_request.head.ref || 'latest' }}
RAW_REF_NAME: ${{ github.event.pull_request.head.ref || github.ref }}
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.0.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v3
with:
submodules: recursive
# Needed for buildx gha cache to work
- name: Expose GitHub Runtime
uses: crazy-max/ghaction-github-runtime@v2
- name: Build container
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
CONTAINER_TAG=$(echo "$RAW_CONTAINER_TAG" | sed 's/[^a-zA-Z0-9]\+/-/')
REF_NAME=$(echo "$RAW_REF_NAME" | sed -r 's#^refs/(heads|tags)/##')
docker buildx build \
--platform "$BUILD_PLATFORMS" \
--tag "$CONTAINER_NAME:$CONTAINER_TAG" \
--label "org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}" \
--label "org.opencontainers.image.documentation=${{ github.server_url }}/${{ github.repository }}" \
--label "org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}/packages" \
--label "org.opencontainers.image.ref.name=$REF_NAME" \
--label "org.opencontainers.image.revision=${{ github.sha }}" \
--label "org.opencontainers.image.vendor=${{ github.repository_owner }}" \
--label "org.opencontainers.image.created=$(date -u --rfc-3339=seconds)" \
--cache-from type=gha \
--cache-to type=gha,mode=max \
--pull ${{ github.event_name == 'push' && '--push' || '' }} .

View File

@@ -14,6 +14,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v2
- uses: actions/checkout@v2
with:
go-version: '1.18.5'
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
uses: golangci/golangci-lint-action@v3

View File

@@ -1,17 +1,20 @@
name: Cross compile WirePorxy
name: Cross compile WireProxy
on:
workflow_dispatch:
create:
tags:
- v*
jobs:
WirePorxy:
WireProxy:
name: Cross compile WirePorxy
name: Cross compile WireProxy
runs-on: ubuntu-20.04
env:
workdir: ./WirePorxy
workdir: ./WireProxy
steps:
- name: Checkout code
@@ -19,7 +22,7 @@ jobs:
with:
fetch-depth: 0
- name: Git clone WirePorxy
- name: Git clone WireProxy
run: |
git clone https://github.com/octeep/wireproxy.git ${{ env.workdir }}
cp ./.github/wireproxy-releaser.yml ${{ env.workdir }}/.goreleaser.yml
@@ -27,7 +30,7 @@ jobs:
- name: Set up GoReleaser
uses: actions/setup-go@v2
with:
go-version: "1.17"
go-version: "1.18"
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
@@ -36,6 +39,8 @@ jobs:
workdir: ${{ env.workdir }}
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release binaries
uses: softprops/action-gh-release@v1
@@ -43,4 +48,4 @@ jobs:
tag_name: wireproxy
files: ${{ env.workdir }}/dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
/main
/wireproxy
*.sw?
/.idea
.goreleaser.yml

19
Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
# Start by building the application.
FROM golang:1.18 as build
WORKDIR /usr/src/wireproxy
COPY . .
RUN CGO_ENABLED=0 go build ./cmd/wireproxy
# Now copy it into our base image.
FROM gcr.io/distroless/static-debian11:nonroot
COPY --from=build /usr/src/wireproxy/wireproxy /usr/bin/wireproxy
VOLUME [ "/etc/wireproxy"]
ENTRYPOINT [ "/usr/bin/wireproxy" ]
CMD [ "--config", "/etc/wireproxy/config" ]
LABEL org.opencontainers.image.title wireproxy
LABEL org.opencontainers.image.description "Wireguard client that exposes itself as a socks5 proxy"
LABEL org.opencontainers.image.licenses ISC

View File

@@ -1,4 +1,8 @@
# wireproxy
[![ISC licensed](https://img.shields.io/badge/license-ISC-blue)](./LICENSE)
[![Build status](https://github.com/octeep/wireproxy/actions/workflows/build.yml/badge.svg)](https://github.com/octeep/wireproxy/actions)
[![Documentation](https://img.shields.io/badge/godoc-wireproxy-blue)](https://pkg.go.dev/github.com/octeep/wireproxy)
A wireguard client that exposes itself as a socks5 proxy or tunnels.
# What is this
@@ -20,6 +24,10 @@ anything.
- TCP static routing for client and server
- SOCKS5 proxy (currently only CONNECT is supported)
# TODO
- UDP Support in SOCKS5
- UDP static routing
# Usage
```
./wireproxy -c [path to config]
@@ -108,6 +116,42 @@ WGConfig = <path to the wireguard config>
...
```
Having multiple peers is also supported. `AllowedIPs` would need to be specified
such that wireproxy would know which peer to forward to.
```
[Interface]
Address = 10.254.254.40/32
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
[Peer]
Endpoint = 192.168.0.204:51820
PublicKey = YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY=
AllowedIPs = 10.254.254.100/32
PersistentKeepalive = 25
[Peer]
PublicKey = ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ=
AllowedIPs = 10.254.254.1/32, fdee:1337:c000:d00d::1/128
Endpoint = 172.16.0.185:44044
PersistentKeepalive = 25
[TCPServerTunnel]
ListenPort = 5000
Target = service-one.servicenet:5000
[TCPServerTunnel]
ListenPort = 5001
Target = service-two.servicenet:5001
[TCPServerTunnel]
ListenPort = 5080
Target = service-three.servicenet:80
```
## Donation
<noscript><a href="https://liberapay.com/octeep/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
## Stargazers over time

View File

@@ -8,22 +8,63 @@ import (
"github.com/akamensky/argparse"
"github.com/octeep/wireproxy"
"suah.dev/protect"
)
// an argument to denote that this process was spawned by -d
const daemonProcess = "daemon-process"
var version = "1.0.4-dev"
// attempts to pledge and panic if it fails
// this does nothing on non-OpenBSD systems
func pledgeOrPanic(promises string) {
err := protect.Pledge(promises)
if err != nil {
log.Fatal(err)
}
}
// attempts to unveil and panic if it fails
// this does nothing on non-OpenBSD systems
func unveilOrPanic(path string, flags string) {
err := protect.Unveil(path, flags)
if err != nil {
log.Fatal(err)
}
}
// get the executable path via syscalls or infer it from argv
func executablePath() string {
programPath, err := os.Executable()
if err != nil {
return os.Args[0]
}
return programPath
}
func main() {
exePath := executablePath()
unveilOrPanic("/", "r")
unveilOrPanic(exePath, "x")
// only allow standard stdio operation, file reading, networking, and exec
// also remove unveil permission to lock unveil
pledgeOrPanic("stdio rpath inet dns proc exec")
isDaemonProcess := len(os.Args) > 1 && os.Args[1] == daemonProcess
args := os.Args
if isDaemonProcess {
// remove proc and exec if they are not needed
pledgeOrPanic("stdio rpath inet dns")
args = []string{args[0]}
args = append(args, os.Args[2:]...)
}
parser := argparse.NewParser("wireproxy", "Userspace wireguard client for proxying")
config := parser.String("c", "config", &argparse.Options{Required: true, Help: "Path of configuration file"})
config := parser.String("c", "config", &argparse.Options{Help: "Path of configuration file"})
daemon := parser.Flag("d", "daemon", &argparse.Options{Help: "Make wireproxy run in background"})
printVerison := parser.Flag("v", "version", &argparse.Options{Help: "Print version"})
configTest := parser.Flag("n", "configtest", &argparse.Options{Help: "Configtest mode. Only check the configuration file for validity."})
err := parser.Parse(args)
@@ -32,9 +73,24 @@ func main() {
return
}
if *printVerison {
fmt.Printf("wireproxy, version %s\n", version)
return
}
if *config == "" {
fmt.Println("configuration path is required")
return
}
if !*daemon {
// remove proc and exec if they are not needed
pledgeOrPanic("stdio rpath inet dns")
}
conf, err := wireproxy.ParseConfig(*config)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
if *configTest {
@@ -49,14 +105,8 @@ func main() {
}
if *daemon {
programPath, err := os.Executable()
if err != nil {
programPath = args[0]
}
newArgs := []string{daemonProcess}
newArgs = append(newArgs, args[1:]...)
cmd := exec.Command(programPath, newArgs...)
args[0] = daemonProcess
cmd := exec.Command(exePath, args...)
err = cmd.Start()
if err != nil {
fmt.Println(err.Error())
@@ -64,9 +114,12 @@ func main() {
return
}
// no file access is allowed from now on, only networking
pledgeOrPanic("stdio inet dns")
tnet, err := wireproxy.StartWireguard(conf.Device)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
for _, spawner := range conf.Routines {

132
config.go
View File

@@ -9,18 +9,24 @@ import (
"github.com/go-ini/ini"
"golang.zx2c4.com/go118/netip"
"net/netip"
)
type PeerConfig struct {
PublicKey string
PreSharedKey string
Endpoint string
KeepAlive int
AllowedIPs []netip.Prefix
}
// DeviceConfig contains the information to initiate a wireguard connection
type DeviceConfig struct {
SelfSecretKey string
SelfEndpoint []netip.Addr
PeerPublicKey string
PeerEndpoint string
DNS []netip.Addr
KeepAlive int
PreSharedKey string
MTU int
SecretKey string
Endpoint []netip.Addr
Peers []PeerConfig
DNS []netip.Addr
MTU int
}
type TCPClientTunnelConfig struct {
@@ -108,7 +114,7 @@ func parseNetIP(section *ini.Section, keyName string) ([]netip.Addr, error) {
return []netip.Addr{}, nil
}
ips := []netip.Addr{}
var ips []netip.Addr
for _, str := range key.StringsWithShadows(",") {
str = strings.TrimSpace(str)
ip, err := netip.ParseAddr(str)
@@ -126,7 +132,7 @@ func parseCIDRNetIP(section *ini.Section, keyName string) ([]netip.Addr, error)
return []netip.Addr{}, nil
}
ips := []netip.Addr{}
var ips []netip.Addr
for _, str := range key.StringsWithShadows(",") {
prefix, err := netip.ParsePrefix(str)
if err != nil {
@@ -143,6 +149,24 @@ func parseCIDRNetIP(section *ini.Section, keyName string) ([]netip.Addr, error)
return ips, nil
}
func parseAllowedIPs(section *ini.Section) ([]netip.Prefix, error) {
key := section.Key("AllowedIPs")
if key == nil {
return []netip.Prefix{}, nil
}
var ips []netip.Prefix
for _, str := range key.StringsWithShadows(",") {
prefix, err := netip.ParsePrefix(str)
if err != nil {
return nil, err
}
ips = append(ips, prefix)
}
return ips, nil
}
func resolveIP(ip string) (*net.IPAddr, error) {
return net.ResolveIPAddr("ip", ip)
}
@@ -160,6 +184,7 @@ func resolveIPPAndPort(addr string) (string, error) {
return net.JoinHostPort(ip.String(), port), nil
}
// ParseInterface parses the [Interface] section and extract the information into `device`
func ParseInterface(cfg *ini.File, device *DeviceConfig) error {
sections, err := cfg.SectionsByName("Interface")
if len(sections) != 1 || err != nil {
@@ -172,13 +197,13 @@ func ParseInterface(cfg *ini.File, device *DeviceConfig) error {
return err
}
device.SelfEndpoint = address
device.Endpoint = address
privKey, err := parseBase64KeyToHex(section, "PrivateKey")
if err != nil {
return err
}
device.SelfSecretKey = privKey
device.SecretKey = privKey
dns, err := parseNetIP(section, "DNS")
if err != nil {
@@ -197,45 +222,58 @@ func ParseInterface(cfg *ini.File, device *DeviceConfig) error {
return nil
}
func ParsePeer(cfg *ini.File, device *DeviceConfig) error {
// ParsePeer parses the [Peer] section and extract the information into `peers`
func ParsePeers(cfg *ini.File, peers *[]PeerConfig) error {
sections, err := cfg.SectionsByName("Peer")
if len(sections) != 1 || err != nil {
return errors.New("one and only one [Peer] is expected")
if len(sections) < 1 || err != nil {
return errors.New("at least one [Peer] is expected")
}
section := sections[0]
decoded, err := parseBase64KeyToHex(section, "PublicKey")
if err != nil {
return err
}
device.PeerPublicKey = decoded
for _, section := range sections {
peer := PeerConfig{
PreSharedKey: "0000000000000000000000000000000000000000000000000000000000000000",
KeepAlive: 0,
}
if sectionKey, err := section.GetKey("PreSharedKey"); err == nil {
value, err := encodeBase64ToHex(sectionKey.String())
decoded, err := parseBase64KeyToHex(section, "PublicKey")
if err != nil {
return err
}
device.PreSharedKey = value
}
peer.PublicKey = decoded
decoded, err = parseString(section, "Endpoint")
if err != nil {
return err
}
decoded, err = resolveIPPAndPort(decoded)
if err != nil {
return err
}
device.PeerEndpoint = decoded
if sectionKey, err := section.GetKey("PreSharedKey"); err == nil {
value, err := encodeBase64ToHex(sectionKey.String())
if err != nil {
return err
}
peer.PreSharedKey = value
}
if sectionKey, err := section.GetKey("PersistentKeepalive"); err == nil {
value, err := sectionKey.Int()
decoded, err = parseString(section, "Endpoint")
if err != nil {
return err
}
device.KeepAlive = value
}
decoded, err = resolveIPPAndPort(decoded)
if err != nil {
return err
}
peer.Endpoint = decoded
if sectionKey, err := section.GetKey("PersistentKeepalive"); err == nil {
value, err := sectionKey.Int()
if err != nil {
return err
}
peer.KeepAlive = value
}
peer.AllowedIPs, err = parseAllowedIPs(section)
if err != nil {
return err
}
*peers = append(*peers, peer)
}
return nil
}
@@ -292,6 +330,8 @@ func parseSocks5Config(section *ini.Section) (RoutineSpawner, error) {
return config, nil
}
// Takes a function that parses an individual section into a config, and apply it on all
// specified sections
func parseRoutinesConfig(routines *[]RoutineSpawner, cfg *ini.File, sectionName string, f func(*ini.Section) (RoutineSpawner, error)) error {
sections, err := cfg.SectionsByName(sectionName)
if err != nil {
@@ -310,10 +350,12 @@ func parseRoutinesConfig(routines *[]RoutineSpawner, cfg *ini.File, sectionName
return nil
}
// ParseConfig takes the path of a configuration file and parses it into Configuration
func ParseConfig(path string) (*Configuration, error) {
iniOpt := ini.LoadOptions{
Insensitive: true,
AllowShadows: true,
Insensitive: true,
AllowShadows: true,
AllowNonUniqueSections: true,
}
cfg, err := ini.LoadSources(iniOpt, path)
@@ -322,9 +364,7 @@ func ParseConfig(path string) (*Configuration, error) {
}
device := &DeviceConfig{
PreSharedKey: "0000000000000000000000000000000000000000000000000000000000000000",
KeepAlive: 0,
MTU: 1420,
MTU: 1420,
}
root := cfg.Section("")
@@ -342,12 +382,12 @@ func ParseConfig(path string) (*Configuration, error) {
return nil, err
}
err = ParsePeer(wgCfg, device)
err = ParsePeers(wgCfg, &device.Peers)
if err != nil {
return nil, err
}
routinesSpawners := []RoutineSpawner{}
var routinesSpawners []RoutineSpawner
err = parseRoutinesConfig(&routinesSpawners, cfg, "TCPClientTunnel", parseTCPClientTunnelConfig)
if err != nil {

View File

@@ -1,14 +0,0 @@
FROM golang:alpine AS go-build
RUN apk --no-cache add --update git
RUN git clone https://github.com/octeep/wireproxy.git
RUN cd ./wireproxy && go build ./cmd/wireproxy
FROM alpine:latest
RUN apk upgrade
COPY --from=go-build /go/wireproxy/wireproxy /usr/bin/
VOLUME [ "/etc/wireproxy"]
ENTRYPOINT [ "/usr/bin/wireproxy", "/etc/wireproxy/config" ]

View File

@@ -1,10 +0,0 @@
build:
docker build -t wireproxy .
run:
docker run \
--rm --tty --interactive \
--name=wireproxy \
--publish 2534:2534 \
--volume "${PWD}/config:/etc/wireproxy/config:ro" \
wireproxy

View File

@@ -1,12 +0,0 @@
[Interface]
Address = ###Interface - Address###
PrivateKey = ###Interface - PrivateKey###
DNS = ###Interface - DNS###
[Peer]
PublicKey = ###Peer - PublicKey###
Endpoint = ###Peer - Endpoint###
# Socks5 create a socks5 proxy on your LAN, and any traffic would be routed via wireguard
[Socks5]
BindAddress = 0.0.0.0:2534

21
go.mod
View File

@@ -1,24 +1,23 @@
module github.com/octeep/wireproxy
go 1.17
go 1.18
require (
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/akamensky/argparse v1.3.1
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/go-ini/ini v1.66.4
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d
golang.zx2c4.com/wireguard v0.0.0-20220202223031-3b95c81cc178
golang.zx2c4.com/wireguard/tun/netstack v0.0.0-20220310012736-ae6bc4dd64e1
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
golang.zx2c4.com/wireguard/tun/netstack v0.0.0-20220703234212-c31a7b1ab478
suah.dev/protect v1.2.0
)
require (
github.com/akamensky/argparse v1.3.1 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6 // indirect
)

44
go.sum
View File

@@ -56,6 +56,8 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A=
github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
@@ -162,7 +164,6 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
@@ -171,6 +172,7 @@ github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -346,7 +348,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -445,6 +446,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -478,7 +480,6 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
@@ -496,15 +497,11 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
@@ -516,6 +513,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
@@ -573,8 +571,8 @@ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -652,7 +650,6 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -742,16 +739,11 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210314195730-07df6a141424/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -760,8 +752,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -825,14 +815,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d h1:9+v0G0naRhLPOJEeJOL6NuXTtAHHwmkyZlgQJ0XcQ8I=
golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d/go.mod h1:5yyfuiqVIJ7t+3MqrpTQ+QqRkMWiESiyDvPNvKYCecg=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20220202223031-3b95c81cc178 h1:Nrf94TOjrvW8nm6N3u2xtbnMZaZudNI9b8nIJH8p8qY=
golang.zx2c4.com/wireguard v0.0.0-20220202223031-3b95c81cc178/go.mod h1:TjUWrnD5ATh7bFvmm/ALEJZQ4ivKbETb6pmyj1vUoNI=
golang.zx2c4.com/wireguard/tun/netstack v0.0.0-20220310012736-ae6bc4dd64e1 h1:7Rwoa4sJmRu2WS/QTimguhoVgFrZG7IzIXHLUE/uXq8=
golang.zx2c4.com/wireguard/tun/netstack v0.0.0-20220310012736-ae6bc4dd64e1/go.mod h1:G+p+j9eRsMJcBS/84MTIxvTZ8Uqdg6hrurXC4/TsLok=
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24 h1:KwsvzlnmErwMd3BXoBSEuL8qU72QxFM/uOUAgZmavRc=
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
golang.zx2c4.com/wireguard/tun/netstack v0.0.0-20220703234212-c31a7b1ab478 h1:xJChlv+mV5zOP1PmNztA+DvfPFonaf253wjShnqM9Fk=
golang.zx2c4.com/wireguard/tun/netstack v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:JexL7LSkdvAJ7GXgsGHKpFeOAv+SuJiHPeRahPLZ9Qk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -959,7 +947,7 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
@@ -999,3 +987,5 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:w
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
suah.dev/protect v1.2.0 h1:4G4V43yVYXCjLFzaE9QJR0fLo3rf5vNBS9YxyoI19DU=
suah.dev/protect v1.2.0/go.mod h1:Ocn1yqUskqe/is6N2bxQxtT+fegbvQsOFyHbJAQu9XE=

10
net.go
View File

@@ -3,8 +3,8 @@
package wireproxy
import (
"golang.zx2c4.com/go118/netip"
"net"
"net/netip"
)
func TCPAddrFromAddrPort(addr netip.AddrPort) *net.TCPAddr {
@@ -14,11 +14,3 @@ func TCPAddrFromAddrPort(addr netip.AddrPort) *net.TCPAddr {
Port: int(addr.Port()),
}
}
func UDPAddrFromAddrPort(addr netip.AddrPort) *net.UDPAddr {
return &net.UDPAddr{
IP: addr.Addr().AsSlice(),
Zone: addr.Addr().Zone(),
Port: int(addr.Port()),
}
}

View File

@@ -4,33 +4,46 @@ import (
"context"
"crypto/subtle"
"errors"
"fmt"
"io"
"log"
"math/rand"
"net"
"os"
"strconv"
"github.com/armon/go-socks5"
"golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/tun/netstack"
"net/netip"
)
// errorLogger is the logger to print error message
var errorLogger = log.New(os.Stderr, "ERROR: ", log.LstdFlags)
// CredentialValidator stores the authentication data of a socks5 proxy
type CredentialValidator struct {
username string
password string
}
// VirtualTun stores a reference to netstack network and DNS configuration
type VirtualTun struct {
tnet *netstack.Net
systemDNS bool
}
// RoutineSpawner spawns a routine (e.g. socks5, tcp static routes) after the configuration is parsed
type RoutineSpawner interface {
SpawnRoutine(vt *VirtualTun)
}
type addressPort struct {
address string
port uint16
}
// LookupAddr lookups a hostname.
// DNS traffic may or may not be routed depending on VirtualTun's setting
func (d VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, error) {
if d.systemDNS {
return net.DefaultResolver.LookupHost(ctx, name)
@@ -39,13 +52,10 @@ func (d VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, erro
}
}
func (d VirtualTun) ResolveAddrPort(saddr string) (*netip.AddrPort, error) {
name, sport, err := net.SplitHostPort(saddr)
if err != nil {
return nil, err
}
addrs, err := d.LookupAddr(context.Background(), name)
// ResolveAddrWithContext resolves a hostname and returns an AddrPort.
// DNS traffic may or may not be routed depending on VirtualTun's setting
func (d VirtualTun) ResolveAddrWithContext(ctx context.Context, name string) (*netip.Addr, error) {
addrs, err := d.LookupAddr(ctx, name)
if err != nil {
return nil, err
}
@@ -55,7 +65,38 @@ func (d VirtualTun) ResolveAddrPort(saddr string) (*netip.AddrPort, error) {
return nil, errors.New("no address found for: " + name)
}
addr, err := netip.ParseAddr(addrs[rand.Intn(size)])
rand.Shuffle(size, func(i, j int) {
addrs[i], addrs[j] = addrs[j], addrs[i]
})
var addr netip.Addr
for _, saddr := range addrs {
addr, err = netip.ParseAddr(saddr)
if err == nil {
break
}
}
if err != nil {
return nil, err
}
return &addr, nil
}
// Resolve resolves a hostname and returns an IP.
// DNS traffic may or may not be routed depending on VirtualTun's setting
func (d VirtualTun) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
addr, err := d.ResolveAddrWithContext(ctx, name)
if err != nil {
return nil, nil, err
}
return ctx, addr.AsSlice(), nil
}
func parseAddressPort(endpoint string) (*addressPort, error) {
name, sport, err := net.SplitHostPort(endpoint)
if err != nil {
return nil, err
}
@@ -65,34 +106,20 @@ func (d VirtualTun) ResolveAddrPort(saddr string) (*netip.AddrPort, error) {
return nil, &net.OpError{Op: "dial", Err: errors.New("port must be numeric")}
}
addrPort := netip.AddrPortFrom(addr, uint16(port))
return &addressPort{address: name, port: uint16(port)}, nil
}
func (d VirtualTun) resolveToAddrPort(endpoint *addressPort) (*netip.AddrPort, error) {
addr, err := d.ResolveAddrWithContext(context.Background(), endpoint.address)
if err != nil {
return nil, err
}
addrPort := netip.AddrPortFrom(*addr, endpoint.port)
return &addrPort, nil
}
func (d VirtualTun) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
var addrs []string
var err error
addrs, err = d.LookupAddr(ctx, name)
if err != nil {
return ctx, nil, err
}
size := len(addrs)
if size == 0 {
return ctx, nil, errors.New("no address found for: " + name)
}
addr := addrs[rand.Intn(size)]
ip := net.ParseIP(addr)
if ip == nil {
return ctx, nil, errors.New("invalid address: " + addr)
}
return ctx, ip, err
}
// SpawnRoutine spawns a socks5 server.
func (config *Socks5Config) SpawnRoutine(vt *VirtualTun) {
conf := &socks5.Config{Dial: vt.tnet.DialContext, Resolver: vt}
if username := config.Username; username != "" {
@@ -102,33 +129,46 @@ func (config *Socks5Config) SpawnRoutine(vt *VirtualTun) {
}
server, err := socks5.New(conf)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
if err := server.ListenAndServe("tcp", config.BindAddress); err != nil {
log.Panic(err)
log.Fatal(err)
}
}
// Valid checks the authentication data in CredentialValidator and compare them
// to username and password in constant time.
func (c CredentialValidator) Valid(username, password string) bool {
u := subtle.ConstantTimeCompare([]byte(c.username), []byte(username))
p := subtle.ConstantTimeCompare([]byte(c.password), []byte(password))
return u&p == 1
}
// connForward copy data from `from` to `to`, then close both stream.
func connForward(bufSize int, from io.ReadWriteCloser, to io.ReadWriteCloser) {
buf := make([]byte, bufSize)
_, err := io.CopyBuffer(to, from, buf)
if err != nil {
to.Close()
return
errorLogger.Printf("Cannot forward traffic: %s\n", err.Error())
}
_ = from.Close()
_ = to.Close()
}
func tcpClientForward(tnet *netstack.Net, target *net.TCPAddr, conn net.Conn) {
sconn, err := tnet.DialTCP(target)
// tcpClientForward starts a new connection via wireguard and forward traffic from `conn`
func tcpClientForward(vt *VirtualTun, raddr *addressPort, conn net.Conn) {
target, err := vt.resolveToAddrPort(raddr)
if err != nil {
fmt.Printf("[ERROR] TCP Client Tunnel to %s: %s\n", target, err.Error())
errorLogger.Printf("TCP Server Tunnel to %s: %s\n", target, err.Error())
return
}
tcpAddr := TCPAddrFromAddrPort(*target)
sconn, err := vt.tnet.DialTCP(tcpAddr)
if err != nil {
errorLogger.Printf("TCP Client Tunnel to %s: %s\n", target, err.Error())
return
}
@@ -136,31 +176,40 @@ func tcpClientForward(tnet *netstack.Net, target *net.TCPAddr, conn net.Conn) {
go connForward(1024, conn, sconn)
}
// SpawnRoutine spawns a local TCP server which acts as a proxy to the specified target
func (conf *TCPClientTunnelConfig) SpawnRoutine(vt *VirtualTun) {
raddr, err := vt.ResolveAddrPort(conf.Target)
raddr, err := parseAddressPort(conf.Target)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
tcpAddr := TCPAddrFromAddrPort(*raddr)
server, err := net.ListenTCP("tcp", conf.BindAddress)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
for {
conn, err := server.Accept()
if err != nil {
log.Panic(err)
log.Fatal(err)
}
go tcpClientForward(vt.tnet, tcpAddr, conn)
go tcpClientForward(vt, raddr, conn)
}
}
func tcpServerForward(target *net.TCPAddr, conn net.Conn) {
sconn, err := net.DialTCP("tcp", nil, target)
// tcpServerForward starts a new connection locally and forward traffic from `conn`
func tcpServerForward(vt *VirtualTun, raddr *addressPort, conn net.Conn) {
target, err := vt.resolveToAddrPort(raddr)
if err != nil {
fmt.Printf("[ERROR] TCP Server Tunnel to %s: %s\n", target, err.Error())
errorLogger.Printf("TCP Server Tunnel to %s: %s\n", target, err.Error())
return
}
tcpAddr := TCPAddrFromAddrPort(*target)
sconn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
errorLogger.Printf("TCP Server Tunnel to %s: %s\n", target, err.Error())
return
}
@@ -168,24 +217,24 @@ func tcpServerForward(target *net.TCPAddr, conn net.Conn) {
go connForward(1024, conn, sconn)
}
// SpawnRoutine spawns a TCP server on wireguard which acts as a proxy to the specified target
func (conf *TCPServerTunnelConfig) SpawnRoutine(vt *VirtualTun) {
raddr, err := vt.ResolveAddrPort(conf.Target)
raddr, err := parseAddressPort(conf.Target)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
tcpAddr := TCPAddrFromAddrPort(*raddr)
addr := &net.TCPAddr{Port: conf.ListenPort}
server, err := vt.tnet.ListenTCP(addr)
if err != nil {
log.Panic(err)
log.Fatal(err)
}
for {
conn, err := server.Accept()
if err != nil {
log.Panic(err)
log.Fatal(err)
}
go tcpServerForward(tcpAddr, conn)
go tcpServerForward(vt, raddr, conn)
}
}

View File

@@ -1,14 +1,18 @@
package wireproxy
import (
"bytes"
"fmt"
"golang.zx2c4.com/go118/netip"
"net/netip"
"github.com/MakeNowJust/heredoc/v2"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun/netstack"
)
// DeviceSetting contains the parameters for setting up a tun interface
type DeviceSetting struct {
ipcRequest string
dns []netip.Addr
@@ -16,18 +20,39 @@ type DeviceSetting struct {
mtu int
}
// serialize the config into an IPC request and DeviceSetting
func createIPCRequest(conf *DeviceConfig) (*DeviceSetting, error) {
request := fmt.Sprintf(`private_key=%s
public_key=%s
endpoint=%s
persistent_keepalive_interval=%d
preshared_key=%s
allowed_ip=0.0.0.0/0`, conf.SelfSecretKey, conf.PeerPublicKey, conf.PeerEndpoint, conf.KeepAlive, conf.PreSharedKey)
var request bytes.Buffer
setting := &DeviceSetting{ipcRequest: request, dns: conf.DNS, deviceAddr: conf.SelfEndpoint, mtu: conf.MTU}
request.WriteString(fmt.Sprintf("private_key=%s\n", conf.SecretKey))
for _, peer := range conf.Peers {
request.WriteString(fmt.Sprintf(heredoc.Doc(`
public_key=%s
endpoint=%s
persistent_keepalive_interval=%d
preshared_key=%s
`),
peer.PublicKey, peer.Endpoint, peer.KeepAlive, peer.PreSharedKey,
))
if len(peer.AllowedIPs) > 0 {
for _, ip := range peer.AllowedIPs {
request.WriteString(fmt.Sprintf("allowed_ip=%s\n", ip.String()))
}
} else {
request.WriteString(heredoc.Doc(`
allowed_ip=0.0.0.0/0
allowed_ip=::0/0
`))
}
}
setting := &DeviceSetting{ipcRequest: request.String(), dns: conf.DNS, deviceAddr: conf.Endpoint, mtu: conf.MTU}
return setting, nil
}
// StartWireguard creates a tun interface on netstack given a configuration
func StartWireguard(conf *DeviceConfig) (*VirtualTun, error) {
setting, err := createIPCRequest(conf)
if err != nil {