Skip to content

Commit f654220

Browse files
marko1777ygurov
andauthored
feat: awg 2.0 (#91)
* feat: ranged H1-H4 * feat: S3, S4 support * chore: updated awg-tools version --------- Co-authored-by: Yaroslav Gurov <[email protected]>
1 parent 1abd24b commit f654220

22 files changed

+1349
-600
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ RUN go mod download && \
66
go build -ldflags '-linkmode external -extldflags "-fno-PIC -static"' -v -o /usr/bin
77

88
FROM alpine:3.19
9-
ARG AWGTOOLS_RELEASE="1.0.20241018"
9+
ARG AWGTOOLS_RELEASE="1.0.20250901"
1010

1111
RUN apk --no-cache add iproute2 iptables bash && \
1212
cd /usr/bin/ && \

device/awg/awg.go

Lines changed: 54 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -3,142 +3,88 @@ package awg
33
import (
44
"bytes"
55
"fmt"
6-
"slices"
7-
"strconv"
8-
"strings"
96
"sync"
107

118
"github.com/tevino/abool"
129
)
1310

14-
type aSecCfgType struct {
15-
IsSet bool
16-
JunkPacketCount int
17-
JunkPacketMinSize int
18-
JunkPacketMaxSize int
19-
InitHeaderJunkSize int
20-
ResponseHeaderJunkSize int
21-
CookieReplyHeaderJunkSize int
22-
TransportHeaderJunkSize int
23-
InitPacketMagicHeader uint32
24-
ResponsePacketMagicHeader uint32
25-
UnderloadPacketMagicHeader uint32
26-
TransportPacketMagicHeader uint32
27-
// InitPacketMagicHeader Limit
28-
// ResponsePacketMagicHeader Limit
29-
// UnderloadPacketMagicHeader Limit
30-
// TransportPacketMagicHeader Limit
31-
}
32-
33-
type Limit struct {
34-
Min uint32
35-
Max uint32
36-
HeaderType uint32
37-
}
38-
39-
func NewLimit(min, max, headerType uint32) (Limit, error) {
40-
if min > max {
41-
return Limit{}, fmt.Errorf("min (%d) cannot be greater than max (%d)", min, max)
42-
}
43-
44-
return Limit{
45-
Min: min,
46-
Max: max,
47-
HeaderType: headerType,
48-
}, nil
49-
}
50-
51-
func ParseMagicHeader(key, value string, defaultHeaderType uint32) (Limit, error) {
52-
// tempAwg.ASecCfg.InitPacketMagicHeader, err = awg.NewLimit(uint32(initPacketMagicHeaderMin), uint32(initPacketMagicHeaderMax), DNewLimit(min, max, headerType)efaultMessageInitiationType)
53-
// var min, max, headerType uint32
54-
// _, err := fmt.Sscanf(value, "%d-%d:%d", &min, &max, &headerType)
55-
// if err != nil {
56-
// return Limit{}, fmt.Errorf("invalid magic header format: %s", value)
57-
// }
58-
59-
limits := strings.Split(value, "-")
60-
if len(limits) != 2 {
61-
return Limit{}, fmt.Errorf("invalid format for key: %s; %s", key, value)
62-
}
63-
64-
min, err := strconv.ParseUint(limits[0], 10, 32)
65-
if err != nil {
66-
return Limit{}, fmt.Errorf("parse min key: %s; value: ; %w", key, limits[0], err)
67-
}
68-
69-
max, err := strconv.ParseUint(limits[1], 10, 32)
70-
if err != nil {
71-
return Limit{}, fmt.Errorf("parse max key: %s; value: ; %w", key, limits[0], err)
72-
}
73-
74-
limit, err := NewLimit(uint32(min), uint32(max), defaultHeaderType)
75-
if err != nil {
76-
return Limit{}, fmt.Errorf("new lmit key: %s; value: ; %w", key, limits[0], err)
77-
}
78-
79-
return limit, nil
80-
}
81-
82-
type Limits []Limit
83-
84-
func NewLimits(limits []Limit) Limits {
85-
slices.SortFunc(limits, func(a, b Limit) int {
86-
if a.Min < b.Min {
87-
return -1
88-
} else if a.Min > b.Min {
89-
return 1
90-
}
91-
return 0
92-
})
93-
94-
return Limits(limits)
11+
type Cfg struct {
12+
IsSet bool
13+
JunkPacketCount int
14+
JunkPacketMinSize int
15+
JunkPacketMaxSize int
16+
InitHeaderJunkSize int
17+
ResponseHeaderJunkSize int
18+
CookieReplyHeaderJunkSize int
19+
TransportHeaderJunkSize int
20+
21+
MagicHeaders MagicHeaders
9522
}
9623

9724
type Protocol struct {
98-
IsASecOn abool.AtomicBool
25+
IsOn abool.AtomicBool
9926
// TODO: revision the need of the mutex
100-
ASecMux sync.RWMutex
101-
ASecCfg aSecCfgType
102-
JunkCreator junkCreator
27+
Mux sync.RWMutex
28+
Cfg Cfg
29+
JunkCreator JunkCreator
10330

10431
HandshakeHandler SpecialHandshakeHandler
10532
}
10633

10734
func (protocol *Protocol) CreateInitHeaderJunk() ([]byte, error) {
108-
return protocol.createHeaderJunk(protocol.ASecCfg.InitHeaderJunkSize)
35+
protocol.Mux.RLock()
36+
defer protocol.Mux.RUnlock()
37+
38+
return protocol.createHeaderJunk(protocol.Cfg.InitHeaderJunkSize, 0)
10939
}
11040

11141
func (protocol *Protocol) CreateResponseHeaderJunk() ([]byte, error) {
112-
return protocol.createHeaderJunk(protocol.ASecCfg.ResponseHeaderJunkSize)
42+
protocol.Mux.RLock()
43+
defer protocol.Mux.RUnlock()
44+
45+
return protocol.createHeaderJunk(protocol.Cfg.ResponseHeaderJunkSize, 0)
11346
}
11447

11548
func (protocol *Protocol) CreateCookieReplyHeaderJunk() ([]byte, error) {
116-
return protocol.createHeaderJunk(protocol.ASecCfg.CookieReplyHeaderJunkSize)
49+
protocol.Mux.RLock()
50+
defer protocol.Mux.RUnlock()
51+
52+
return protocol.createHeaderJunk(protocol.Cfg.CookieReplyHeaderJunkSize, 0)
11753
}
11854

11955
func (protocol *Protocol) CreateTransportHeaderJunk(packetSize int) ([]byte, error) {
120-
return protocol.createHeaderJunk(protocol.ASecCfg.TransportHeaderJunkSize, packetSize)
56+
protocol.Mux.RLock()
57+
defer protocol.Mux.RUnlock()
58+
59+
return protocol.createHeaderJunk(protocol.Cfg.TransportHeaderJunkSize, packetSize)
12160
}
12261

123-
func (protocol *Protocol) createHeaderJunk(junkSize int, optExtraSize ...int) ([]byte, error) {
124-
extraSize := 0
125-
if len(optExtraSize) == 1 {
126-
extraSize = optExtraSize[0]
62+
func (protocol *Protocol) createHeaderJunk(junkSize int, extraSize int) ([]byte, error) {
63+
if junkSize == 0 {
64+
return nil, nil
65+
}
66+
67+
buf := make([]byte, 0, junkSize+extraSize)
68+
writer := bytes.NewBuffer(buf[:0])
69+
70+
err := protocol.JunkCreator.AppendJunk(writer, junkSize)
71+
if err != nil {
72+
return nil, fmt.Errorf("append junk: %w", err)
12773
}
12874

129-
var junk []byte
130-
protocol.ASecMux.RLock()
131-
if junkSize != 0 {
132-
buf := make([]byte, 0, junkSize+extraSize)
133-
writer := bytes.NewBuffer(buf[:0])
134-
err := protocol.JunkCreator.AppendJunk(writer, junkSize)
135-
if err != nil {
136-
protocol.ASecMux.RUnlock()
137-
return nil, err
75+
return writer.Bytes(), nil
76+
}
77+
78+
func (protocol *Protocol) GetMagicHeaderMinFor(msgType uint32) (uint32, error) {
79+
for _, magicHeader := range protocol.Cfg.MagicHeaders.Values {
80+
if magicHeader.Min <= msgType && msgType <= magicHeader.Max {
81+
return magicHeader.Min, nil
13882
}
139-
junk = writer.Bytes()
14083
}
141-
protocol.ASecMux.RUnlock()
14284

143-
return junk, nil
85+
return 0, fmt.Errorf("no header for value: %d", msgType)
86+
}
87+
88+
func (protocol *Protocol) GetMsgType(defaultMsgType uint32) (uint32, error) {
89+
return protocol.Cfg.MagicHeaders.Get(defaultMsgType)
14490
}

device/awg/junk_creator.go

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,49 @@ package awg
22

33
import (
44
"bytes"
5-
crand "crypto/rand"
65
"fmt"
7-
v2 "math/rand/v2"
86
)
97

10-
type junkCreator struct {
11-
aSecCfg aSecCfgType
12-
cha8Rand *v2.ChaCha8
8+
type JunkCreator struct {
9+
cfg Cfg
10+
randomGenerator PRNG[int]
1311
}
1412

1513
// TODO: refactor param to only pass the junk related params
16-
func NewJunkCreator(aSecCfg aSecCfgType) (junkCreator, error) {
17-
buf := make([]byte, 32)
18-
_, err := crand.Read(buf)
19-
if err != nil {
20-
return junkCreator{}, err
21-
}
22-
return junkCreator{aSecCfg: aSecCfg, cha8Rand: v2.NewChaCha8([32]byte(buf))}, nil
14+
func NewJunkCreator(cfg Cfg) JunkCreator {
15+
return JunkCreator{cfg: cfg, randomGenerator: NewPRNG[int]()}
2316
}
2417

25-
// Should be called with aSecMux RLocked
26-
func (jc *junkCreator) CreateJunkPackets(junks *[][]byte) error {
27-
if jc.aSecCfg.JunkPacketCount == 0 {
28-
return nil
18+
// Should be called with awg mux RLocked
19+
func (jc *JunkCreator) CreateJunkPackets(junks *[][]byte) {
20+
if jc.cfg.JunkPacketCount == 0 {
21+
return
2922
}
3023

31-
for range jc.aSecCfg.JunkPacketCount {
24+
for range jc.cfg.JunkPacketCount {
3225
packetSize := jc.randomPacketSize()
33-
junk, err := jc.randomJunkWithSize(packetSize)
34-
if err != nil {
35-
return fmt.Errorf("create junk packet: %v", err)
36-
}
26+
junk := jc.randomJunkWithSize(packetSize)
3727
*junks = append(*junks, junk)
3828
}
39-
return nil
29+
return
4030
}
4131

42-
// Should be called with aSecMux RLocked
43-
func (jc *junkCreator) randomPacketSize() int {
44-
return int(
45-
jc.cha8Rand.Uint64()%uint64(
46-
jc.aSecCfg.JunkPacketMaxSize-jc.aSecCfg.JunkPacketMinSize,
47-
),
48-
) + jc.aSecCfg.JunkPacketMinSize
32+
// Should be called with awg mux RLocked
33+
func (jc *JunkCreator) randomPacketSize() int {
34+
return jc.randomGenerator.RandomSizeInRange(jc.cfg.JunkPacketMinSize, jc.cfg.JunkPacketMaxSize)
4935
}
5036

51-
// Should be called with aSecMux RLocked
52-
func (jc *junkCreator) AppendJunk(writer *bytes.Buffer, size int) error {
53-
headerJunk, err := jc.randomJunkWithSize(size)
54-
if err != nil {
55-
return fmt.Errorf("create header junk: %v", err)
56-
}
57-
_, err = writer.Write(headerJunk)
37+
// Should be called with awg mux RLocked
38+
func (jc *JunkCreator) AppendJunk(writer *bytes.Buffer, size int) error {
39+
headerJunk := jc.randomJunkWithSize(size)
40+
_, err := writer.Write(headerJunk)
5841
if err != nil {
5942
return fmt.Errorf("write header junk: %v", err)
6043
}
6144
return nil
6245
}
6346

64-
// Should be called with aSecMux RLocked
65-
func (jc *junkCreator) randomJunkWithSize(size int) ([]byte, error) {
66-
// TODO: use a memory pool to allocate
67-
junk := make([]byte, size)
68-
_, err := jc.cha8Rand.Read(junk)
69-
return junk, err
47+
// Should be called with awg mux RLocked
48+
func (jc *JunkCreator) randomJunkWithSize(size int) []byte {
49+
return jc.randomGenerator.ReadSize(size)
7050
}

0 commit comments

Comments
 (0)