Skip to content

Commit

Permalink
Add support for AmneziaWG (#1)
Browse files Browse the repository at this point in the history
* Add support for AmneziaWG

* Add validations

* Update README

* Update go and package name

* Update versions
  • Loading branch information
artem-russkikh authored Sep 2, 2024
1 parent cb1f39b commit 92cfca9
Show file tree
Hide file tree
Showing 15 changed files with 474 additions and 66 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Windows amd64 Version
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o WireProxy_amd64.exe -v ./cmd/wireproxy
Expand All @@ -37,7 +37,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Windows arm64 Version
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -o WireProxy_arm64.exe -v ./cmd/wireproxy
Expand All @@ -57,7 +57,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Linux amd64 Version
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o WireProxy_amd64 -v ./cmd/wireproxy
Expand All @@ -77,7 +77,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Linux arm64 Version
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o WireProxy_arm64 -v ./cmd/wireproxy
Expand All @@ -97,7 +97,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Linux s390x Version
run: |
CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o WireProxy_s390x -v ./cmd/wireproxy
Expand All @@ -117,7 +117,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Darwin amd64 Version
run: |
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o WireProxy_amd64 -v ./cmd/wireproxy
Expand All @@ -137,7 +137,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Building Darwin arm64 Version
run: |
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o WireProxy_arm64 -v ./cmd/wireproxy
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: '1.23'
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
with:
version: latest
version: latest
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Setting up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
- name: Install dependencies
run: sudo apt install wireguard curl
- name: Building wireproxy
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/wireproxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ jobs:

- name: Git clone WireProxy
run: |
git clone https://github.com/pufferffish/wireproxy.git ${{ env.workdir }}
git clone https://github.com/artem-russkikh/wireproxy-awg.git ${{ env.workdir }}
cp ./.github/wireproxy-releaser.yml ${{ env.workdir }}/.goreleaser.yml
- name: Set up GoReleaser
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Start by building the application.
FROM docker.io/golang:1.21 as build
FROM docker.io/golang:1.23 as build

WORKDIR /usr/src/wireproxy
COPY . .
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![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/http proxy or tunnels.
AmneziaWG compatible wireguard client that exposes itself as a socks5/http proxy or tunnels. Forked from [wireproxy](https://github.com/pufferffish/wireproxy)

# What is this
`wireproxy` is a completely userspace application that connects to a wireguard peer,
Expand All @@ -20,8 +20,8 @@ and configured my browser to use wireproxy for certain sites. It's pretty useful
wireproxy is completely isolated from my network interfaces, and I don't need root to configure
anything.

Users who want something similar but for Amnezia VPN can use [this fork](https://github.com/juev/wireproxy/tree/feature/amnezia-go)
of wireproxy by [@juev](https://github.com/juev).
Users who want something similar but for Amnezia VPN can use [this fork](https://github.com/artem-russkikh/wireproxy-awg)
of wireproxy by [@artem-russkikh](https://github.com/artem-russkikh).

# Feature
- TCP static routing for client and server
Expand Down
18 changes: 9 additions & 9 deletions cmd/wireproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"syscall"

"github.com/akamensky/argparse"
"github.com/pufferffish/wireproxy"
"golang.zx2c4.com/wireguard/device"
"github.com/amnezia-vpn/amneziawg-go/device"
wireproxyawg "github.com/artem-russkikh/wireproxy-awg"
"suah.dev/protect"
)

Expand Down Expand Up @@ -130,21 +130,21 @@ func extractPort(addr string) uint16 {
return uint16(port)
}

func lockNetwork(sections []wireproxy.RoutineSpawner, infoAddr *string) {
func lockNetwork(sections []wireproxyawg.RoutineSpawner, infoAddr *string) {
var rules []landlock.Rule
if infoAddr != nil && *infoAddr != "" {
rules = append(rules, landlock.BindTCP(extractPort(*infoAddr)))
}

for _, section := range sections {
switch section := section.(type) {
case *wireproxy.TCPServerTunnelConfig:
case *wireproxyawg.TCPServerTunnelConfig:
rules = append(rules, landlock.ConnectTCP(extractPort(section.Target)))
case *wireproxy.HTTPConfig:
case *wireproxyawg.HTTPConfig:
rules = append(rules, landlock.BindTCP(extractPort(section.BindAddress)))
case *wireproxy.TCPClientTunnelConfig:
case *wireproxyawg.TCPClientTunnelConfig:
rules = append(rules, landlock.ConnectTCP(uint16(section.BindAddress.Port)))
case *wireproxy.Socks5Config:
case *wireproxyawg.Socks5Config:
rules = append(rules, landlock.BindTCP(extractPort(section.BindAddress)))
}
}
Expand Down Expand Up @@ -205,7 +205,7 @@ func main() {
lock("read-config")
}

conf, err := wireproxy.ParseConfig(*config)
conf, err := wireproxyawg.ParseConfig(*config)
if err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -244,7 +244,7 @@ func main() {

lock("ready")

tun, err := wireproxy.StartWireguard(conf.Device, logLevel)
tun, err := wireproxyawg.StartWireguard(conf.Device, logLevel)
if err != nil {
log.Fatal(err)
}
Expand Down
166 changes: 166 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ type PeerConfig struct {
AllowedIPs []netip.Prefix
}

type ASecConfigType struct {
junkPacketCount int // Jc
junkPacketMinSize int // Jmin
junkPacketMaxSize int // Jmax
initPacketJunkSize int // s1
responsePacketJunkSize int // s2
initPacketMagicHeader uint32 // h1
responsePacketMagicHeader uint32 // h2
underloadPacketMagicHeader uint32 // h3
transportPacketMagicHeader uint32 // h4
}

// DeviceConfig contains the information to initiate a wireguard connection
type DeviceConfig struct {
SecretKey string
Expand All @@ -31,6 +43,7 @@ type DeviceConfig struct {
ListenPort *int
CheckAlive []netip.Addr
CheckAliveInterval int
ASecConfig *ASecConfigType
}

type TCPClientTunnelConfig struct {
Expand Down Expand Up @@ -296,6 +309,159 @@ func ParseInterface(cfg *ini.File, device *DeviceConfig) error {
device.CheckAliveInterval = value
}

aSecConfig, err := ParseASecConfig(section)
if err != nil {
return err
}
device.ASecConfig = aSecConfig

return nil
}

func ParseASecConfig(section *ini.Section) (*ASecConfigType, error) {
var aSecConfig *ASecConfigType

if sectionKey, err := section.GetKey("Jc"); err == nil {
value, err := sectionKey.Int()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.junkPacketCount = value
}

if sectionKey, err := section.GetKey("Jmin"); err == nil {
value, err := sectionKey.Int()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.junkPacketMinSize = value
}

if sectionKey, err := section.GetKey("Jmax"); err == nil {
value, err := sectionKey.Int()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.junkPacketMaxSize = value
}

if sectionKey, err := section.GetKey("S1"); err == nil {
value, err := sectionKey.Int()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.initPacketJunkSize = value
}

if sectionKey, err := section.GetKey("S2"); err == nil {
value, err := sectionKey.Int()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.responsePacketJunkSize = value
}

if sectionKey, err := section.GetKey("H1"); err == nil {
value, err := sectionKey.Uint()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.initPacketMagicHeader = uint32(value)
}

if sectionKey, err := section.GetKey("H2"); err == nil {
value, err := sectionKey.Uint()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.responsePacketMagicHeader = uint32(value)
}

if sectionKey, err := section.GetKey("H3"); err == nil {
value, err := sectionKey.Uint()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.underloadPacketMagicHeader = uint32(value)
}

if sectionKey, err := section.GetKey("H4"); err == nil {
value, err := sectionKey.Uint()
if err != nil {
return nil, err
}
if aSecConfig == nil {
aSecConfig = &ASecConfigType{}
}
aSecConfig.transportPacketMagicHeader = uint32(value)
}

if err := ValidateASecConfig(aSecConfig); err != nil {
return nil, err
}

return aSecConfig, nil
}

func ValidateASecConfig(config *ASecConfigType) error {
if config == nil {
return nil
}
jc := config.junkPacketCount
jmin := config.junkPacketMinSize
jmax := config.junkPacketMaxSize
if jc < 1 || jc > 128 {
return errors.New("value of the Jc field must be within the range of 1 to 128")
}
if jmin > jmax {
return errors.New("value of the Jmin field must be less than or equal to Jmax field value")
}
if jmax > 1280 {
return errors.New("value of the Jmax field must be less than or equal 1280")
}

s1 := config.initPacketJunkSize
s2 := config.responsePacketJunkSize
const messageInitiationSize = 148
const messageResponseSize = 92
if messageInitiationSize+s1 == messageResponseSize+s2 {
return errors.New(
"value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)",
)
}

h1 := config.initPacketMagicHeader
h2 := config.responsePacketMagicHeader
h3 := config.underloadPacketMagicHeader
h4 := config.transportPacketMagicHeader
if (h1 == h2) || (h1 == h3) || (h1 == h4) || (h2 == h3) || (h2 == h4) || (h3 == h4) {
return errors.New("values of the H1-H4 fields must be unique")
}

return nil
}

Expand Down
Loading

0 comments on commit 92cfca9

Please sign in to comment.