mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2025-06-07 13:53:44 +02:00
Advanced security header layer & config
Signed-off-by: Mark Puha <marko10@inf.elte.hu>
This commit is contained in:
parent
469159ecf7
commit
1f0f5d5b7c
16 changed files with 536 additions and 51 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,4 @@
|
||||||
wireguard-go
|
wireguard-go
|
||||||
|
cfg/cfg_values.go
|
||||||
|
generator.exe
|
||||||
|
generator
|
24
Makefile
24
Makefile
|
@ -29,3 +29,27 @@ clean:
|
||||||
rm -f wireguard-go
|
rm -f wireguard-go
|
||||||
|
|
||||||
.PHONY: all clean test install generate-version-and-build
|
.PHONY: all clean test install generate-version-and-build
|
||||||
|
|
||||||
|
|
||||||
|
has_args =
|
||||||
|
# If the first argument is "cfg_gen"...
|
||||||
|
ifeq (cfg_gen,$(firstword $(MAKECMDGOALS)))
|
||||||
|
has_args = yes
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef has_args
|
||||||
|
# use the rest as arguments for "cfg_gen"
|
||||||
|
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
||||||
|
# ...and turn them into do-nothing targets
|
||||||
|
$(eval $(RUN_ARGS):;@:)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
gen_run=generator.exe
|
||||||
|
else
|
||||||
|
gen_run=./generator
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: cfg_gen
|
||||||
|
cfg_gen:
|
||||||
|
go build util/cfgGenerator/generator.go && $(gen_run) $(RUN_ARGS)
|
|
@ -4,6 +4,14 @@ This is an implementation of WireGuard in Go.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Config gen
|
||||||
|
The configs are generate from a yml file. If you want to change the config run `make cfg_gen config_name` where `config_name` is the name of the yaml file you'd like to generate from. The script will search in the `cfg/settings/` folder
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
`make cfg_gen default` will generate a config from `cfg/settings/default.yml` the file will be called `cfg/cfg_values.go`
|
||||||
|
|
||||||
|
Every time you make changes to the yml you need to rerun this.
|
||||||
|
|
||||||
Most Linux kernel WireGuard users are used to adding an interface with `ip link add wg0 type wireguard`. With wireguard-go, instead simply run:
|
Most Linux kernel WireGuard users are used to adding an interface with `ip link add wg0 type wireguard`. With wireguard-go, instead simply run:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
55
cfg/cfg_def.go
Normal file
55
cfg/cfg_def.go
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package cfg
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if IsAdvancedSecurityOn() {
|
||||||
|
if JunkPacketMaxSize <= JunkPacketMinSize {
|
||||||
|
log.Fatalf(
|
||||||
|
"MaxSize: %d; should be greater than MinSize: %d",
|
||||||
|
JunkPacketMaxSize,
|
||||||
|
JunkPacketMinSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if JunkPacketCount < 0 {
|
||||||
|
log.Fatalf("JunkPacketCount should be non negative")
|
||||||
|
}
|
||||||
|
const MaxSegmentSize = 2048 - 32
|
||||||
|
if 148+InitPacketJunkSize >= MaxSegmentSize {
|
||||||
|
log.Fatalf(
|
||||||
|
"init packets should be smaller than maxSegmentSize: %d",
|
||||||
|
MaxSegmentSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if 92+ResponsePacketJunkSize >= MaxSegmentSize {
|
||||||
|
log.Fatalf(
|
||||||
|
"response packets should be smaller than maxSegmentSize: %d",
|
||||||
|
MaxSegmentSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if 64+UnderLoadPacketJunkSize >= MaxSegmentSize {
|
||||||
|
log.Fatalf(
|
||||||
|
"underload packets should be smaller than maxSegmentSize: %d",
|
||||||
|
MaxSegmentSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if 32+TransportPacketJunkSize >= MaxSegmentSize {
|
||||||
|
log.Fatalf(
|
||||||
|
"transport packets should be smaller than maxSegmentSize: %d",
|
||||||
|
MaxSegmentSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if InitPacketJunkSize != 0 ||
|
||||||
|
ResponsePacketJunkSize != 0 ||
|
||||||
|
UnderLoadPacketJunkSize != 0 ||
|
||||||
|
TransportPacketJunkSize != 0 {
|
||||||
|
|
||||||
|
log.Fatal("JunkSizes should be zero when advanced security on")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAdvancedSecurityOn() bool {
|
||||||
|
return InitPacketMagicHeader != 1
|
||||||
|
}
|
11
cfg/settings/advanced_security_off.yml
Normal file
11
cfg/settings/advanced_security_off.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
junk_packet_count: 5
|
||||||
|
junk_packet_min_size: 10
|
||||||
|
junk_packet_max_size: 30
|
||||||
|
init_packet_junk_size: 0
|
||||||
|
response_packet_junk_size: 0
|
||||||
|
underload_packet_junk_size: 0
|
||||||
|
transport_packet_junk_size: 0
|
||||||
|
init_packet_magic_header: 1
|
||||||
|
response_packet_magic_header : 2
|
||||||
|
underload_packet_magic_header : 3
|
||||||
|
transport_packet_magic_header : 4
|
11
cfg/settings/default.yml
Normal file
11
cfg/settings/default.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
junk_packet_count: 5
|
||||||
|
junk_packet_min_size: 10
|
||||||
|
junk_packet_max_size: 30
|
||||||
|
init_packet_junk_size: 30
|
||||||
|
response_packet_junk_size: 50
|
||||||
|
underload_packet_junk_size: 0
|
||||||
|
transport_packet_junk_size: 0
|
||||||
|
init_packet_magic_header: 1234567
|
||||||
|
response_packet_magic_header : 7654321
|
||||||
|
underload_packet_magic_header : 12345687
|
||||||
|
transport_packet_magic_header : 146810
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/crypto/poly1305"
|
"golang.org/x/crypto/poly1305"
|
||||||
|
|
||||||
|
"golang.zx2c4.com/wireguard/cfg"
|
||||||
"golang.zx2c4.com/wireguard/tai64n"
|
"golang.zx2c4.com/wireguard/tai64n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -53,10 +54,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MessageInitiationType = 1
|
MessageInitiationType = cfg.InitPacketMagicHeader
|
||||||
MessageResponseType = 2
|
MessageResponseType = cfg.ResponsePacketMagicHeader
|
||||||
MessageCookieReplyType = 3
|
MessageCookieReplyType = cfg.UnderloadPacketMagicHeader
|
||||||
MessageTransportType = 4
|
MessageTransportType = cfg.TransportPacketMagicHeader
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -75,6 +76,20 @@ const (
|
||||||
MessageTransportOffsetContent = 16
|
MessageTransportOffsetContent = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var packetSizeToMsgType = map[int]uint32{
|
||||||
|
MessageInitiationSize + cfg.InitPacketJunkSize: MessageInitiationType,
|
||||||
|
MessageResponseSize + cfg.ResponsePacketJunkSize: MessageResponseType,
|
||||||
|
MessageCookieReplySize + cfg.UnderLoadPacketJunkSize: MessageCookieReplyType,
|
||||||
|
MessageTransportSize + cfg.TransportPacketJunkSize: MessageTransportType,
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgTypeToJunkSize = map[uint32]int{
|
||||||
|
MessageInitiationType: cfg.InitPacketJunkSize,
|
||||||
|
MessageResponseType: cfg.ResponsePacketJunkSize,
|
||||||
|
MessageCookieReplyType: cfg.UnderLoadPacketJunkSize,
|
||||||
|
MessageTransportType: cfg.TransportPacketJunkSize,
|
||||||
|
}
|
||||||
|
|
||||||
/* Type is an 8-bit field, followed by 3 nul bytes,
|
/* Type is an 8-bit field, followed by 3 nul bytes,
|
||||||
* by marshalling the messages in little-endian byteorder
|
* by marshalling the messages in little-endian byteorder
|
||||||
* we can treat these as a 32-bit unsigned int (for now)
|
* we can treat these as a 32-bit unsigned int (for now)
|
||||||
|
@ -174,7 +189,9 @@ func init() {
|
||||||
mixHash(&InitialHash, &InitialChainKey, []byte(WGIdentifier))
|
mixHash(&InitialHash, &InitialChainKey, []byte(WGIdentifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, error) {
|
func (device *Device) CreateMessageInitiation(
|
||||||
|
peer *Peer,
|
||||||
|
) (*MessageInitiation, error) {
|
||||||
device.staticIdentity.RLock()
|
device.staticIdentity.RLock()
|
||||||
defer device.staticIdentity.RUnlock()
|
defer device.staticIdentity.RUnlock()
|
||||||
|
|
||||||
|
@ -214,7 +231,12 @@ func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, e
|
||||||
ss[:],
|
ss[:],
|
||||||
)
|
)
|
||||||
aead, _ := chacha20poly1305.New(key[:])
|
aead, _ := chacha20poly1305.New(key[:])
|
||||||
aead.Seal(msg.Static[:0], ZeroNonce[:], device.staticIdentity.publicKey[:], handshake.hash[:])
|
aead.Seal(
|
||||||
|
msg.Static[:0],
|
||||||
|
ZeroNonce[:],
|
||||||
|
device.staticIdentity.publicKey[:],
|
||||||
|
handshake.hash[:],
|
||||||
|
)
|
||||||
handshake.mixHash(msg.Static[:])
|
handshake.mixHash(msg.Static[:])
|
||||||
|
|
||||||
// encrypt timestamp
|
// encrypt timestamp
|
||||||
|
@ -312,14 +334,23 @@ func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation) *Peer {
|
||||||
// protect against replay & flood
|
// protect against replay & flood
|
||||||
|
|
||||||
replay := !timestamp.After(handshake.lastTimestamp)
|
replay := !timestamp.After(handshake.lastTimestamp)
|
||||||
flood := time.Since(handshake.lastInitiationConsumption) <= HandshakeInitationRate
|
flood := time.Since(
|
||||||
|
handshake.lastInitiationConsumption,
|
||||||
|
) <= HandshakeInitationRate
|
||||||
handshake.mutex.RUnlock()
|
handshake.mutex.RUnlock()
|
||||||
if replay {
|
if replay {
|
||||||
device.log.Verbosef("%v - ConsumeMessageInitiation: handshake replay @ %v", peer, timestamp)
|
device.log.Verbosef(
|
||||||
|
"%v - ConsumeMessageInitiation: handshake replay @ %v",
|
||||||
|
peer,
|
||||||
|
timestamp,
|
||||||
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if flood {
|
if flood {
|
||||||
device.log.Verbosef("%v - ConsumeMessageInitiation: handshake flood", peer)
|
device.log.Verbosef(
|
||||||
|
"%v - ConsumeMessageInitiation: handshake flood",
|
||||||
|
peer,
|
||||||
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +379,9 @@ func (device *Device) ConsumeMessageInitiation(msg *MessageInitiation) *Peer {
|
||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) CreateMessageResponse(peer *Peer) (*MessageResponse, error) {
|
func (device *Device) CreateMessageResponse(
|
||||||
|
peer *Peer,
|
||||||
|
) (*MessageResponse, error) {
|
||||||
handshake := &peer.handshake
|
handshake := &peer.handshake
|
||||||
handshake.mutex.Lock()
|
handshake.mutex.Lock()
|
||||||
defer handshake.mutex.Unlock()
|
defer handshake.mutex.Unlock()
|
||||||
|
@ -361,7 +394,10 @@ func (device *Device) CreateMessageResponse(peer *Peer) (*MessageResponse, error
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
device.indexTable.Delete(handshake.localIndex)
|
device.indexTable.Delete(handshake.localIndex)
|
||||||
handshake.localIndex, err = device.indexTable.NewIndexForHandshake(peer, handshake)
|
handshake.localIndex, err = device.indexTable.NewIndexForHandshake(
|
||||||
|
peer,
|
||||||
|
handshake,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -551,7 +587,9 @@ func (peer *Peer) BeginSymmetricSession() error {
|
||||||
// zero handshake
|
// zero handshake
|
||||||
|
|
||||||
setZero(handshake.chainKey[:])
|
setZero(handshake.chainKey[:])
|
||||||
setZero(handshake.hash[:]) // Doesn't necessarily need to be zeroed. Could be used for something interesting down the line.
|
setZero(
|
||||||
|
handshake.hash[:],
|
||||||
|
) // Doesn't necessarily need to be zeroed. Could be used for something interesting down the line.
|
||||||
setZero(handshake.localEphemeral[:])
|
setZero(handshake.localEphemeral[:])
|
||||||
peer.handshake.state = handshakeZeroed
|
peer.handshake.state = handshakeZeroed
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
|
"golang.zx2c4.com/wireguard/cfg"
|
||||||
"golang.zx2c4.com/wireguard/conn"
|
"golang.zx2c4.com/wireguard/conn"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,7 +56,10 @@ func (peer *Peer) keepKeyFreshReceiving() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
keypair := peer.keypairs.Current()
|
keypair := peer.keypairs.Current()
|
||||||
if keypair != nil && keypair.isInitiator && time.Since(keypair.created) > (RejectAfterTime-KeepaliveTimeout-RekeyTimeout) {
|
if keypair != nil && keypair.isInitiator &&
|
||||||
|
time.Since(
|
||||||
|
keypair.created,
|
||||||
|
) > (RejectAfterTime-KeepaliveTimeout-RekeyTimeout) {
|
||||||
peer.timers.sentLastMinuteHandshake.Store(true)
|
peer.timers.sentLastMinuteHandshake.Store(true)
|
||||||
peer.SendHandshakeInitiation(false)
|
peer.SendHandshakeInitiation(false)
|
||||||
}
|
}
|
||||||
|
@ -66,7 +70,10 @@ func (peer *Peer) keepKeyFreshReceiving() {
|
||||||
* Every time the bind is updated a new routine is started for
|
* Every time the bind is updated a new routine is started for
|
||||||
* IPv4 and IPv6 (separately)
|
* IPv4 and IPv6 (separately)
|
||||||
*/
|
*/
|
||||||
func (device *Device) RoutineReceiveIncoming(maxBatchSize int, recv conn.ReceiveFunc) {
|
func (device *Device) RoutineReceiveIncoming(
|
||||||
|
maxBatchSize int,
|
||||||
|
recv conn.ReceiveFunc,
|
||||||
|
) {
|
||||||
recvName := recv.PrettyName()
|
recvName := recv.PrettyName()
|
||||||
defer func() {
|
defer func() {
|
||||||
device.log.Verbosef("Routine: receive incoming %s - stopped", recvName)
|
device.log.Verbosef("Routine: receive incoming %s - stopped", recvName)
|
||||||
|
@ -109,7 +116,11 @@ func (device *Device) RoutineReceiveIncoming(maxBatchSize int, recv conn.Receive
|
||||||
if errors.Is(err, net.ErrClosed) {
|
if errors.Is(err, net.ErrClosed) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
device.log.Verbosef("Failed to receive %s packet: %v", recvName, err)
|
device.log.Verbosef(
|
||||||
|
"Failed to receive %s packet: %v",
|
||||||
|
recvName,
|
||||||
|
err,
|
||||||
|
)
|
||||||
if neterr, ok := err.(net.Error); ok && !neterr.Temporary() {
|
if neterr, ok := err.(net.Error); ok && !neterr.Temporary() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -131,8 +142,17 @@ func (device *Device) RoutineReceiveIncoming(maxBatchSize int, recv conn.Receive
|
||||||
// check size of packet
|
// check size of packet
|
||||||
|
|
||||||
packet := bufsArrs[i][:size]
|
packet := bufsArrs[i][:size]
|
||||||
|
if cfg.IsAdvancedSecurityOn() {
|
||||||
|
var junkSize int
|
||||||
|
if mapMsgType, ok := packetSizeToMsgType[size]; ok {
|
||||||
|
junkSize = msgTypeToJunkSize[mapMsgType]
|
||||||
|
} else {
|
||||||
|
junkSize = cfg.TransportPacketJunkSize
|
||||||
|
}
|
||||||
|
// shift junk
|
||||||
|
packet = packet[junkSize:]
|
||||||
|
}
|
||||||
msgType := binary.LittleEndian.Uint32(packet[:4])
|
msgType := binary.LittleEndian.Uint32(packet[:4])
|
||||||
|
|
||||||
switch msgType {
|
switch msgType {
|
||||||
|
|
||||||
// check if transport
|
// check if transport
|
||||||
|
@ -302,9 +322,14 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
// consume reply
|
// consume reply
|
||||||
|
|
||||||
if peer := entry.peer; peer.isRunning.Load() {
|
if peer := entry.peer; peer.isRunning.Load() {
|
||||||
device.log.Verbosef("Receiving cookie response from %s", elem.endpoint.DstToString())
|
device.log.Verbosef(
|
||||||
|
"Receiving cookie response from %s",
|
||||||
|
elem.endpoint.DstToString(),
|
||||||
|
)
|
||||||
if !peer.cookieGenerator.ConsumeReply(&reply) {
|
if !peer.cookieGenerator.ConsumeReply(&reply) {
|
||||||
device.log.Verbosef("Could not decrypt invalid cookie response")
|
device.log.Verbosef(
|
||||||
|
"Could not decrypt invalid cookie response",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +350,10 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
|
|
||||||
// verify MAC2 field
|
// verify MAC2 field
|
||||||
|
|
||||||
if !device.cookieChecker.CheckMAC2(elem.packet, elem.endpoint.DstToBytes()) {
|
if !device.cookieChecker.CheckMAC2(
|
||||||
|
elem.packet,
|
||||||
|
elem.endpoint.DstToBytes(),
|
||||||
|
) {
|
||||||
device.SendHandshakeCookie(&elem)
|
device.SendHandshakeCookie(&elem)
|
||||||
goto skip
|
goto skip
|
||||||
}
|
}
|
||||||
|
@ -346,9 +374,7 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
|
|
||||||
switch elem.msgType {
|
switch elem.msgType {
|
||||||
case MessageInitiationType:
|
case MessageInitiationType:
|
||||||
|
|
||||||
// unmarshal
|
// unmarshal
|
||||||
|
|
||||||
var msg MessageInitiation
|
var msg MessageInitiation
|
||||||
reader := bytes.NewReader(elem.packet)
|
reader := bytes.NewReader(elem.packet)
|
||||||
err := binary.Read(reader, binary.LittleEndian, &msg)
|
err := binary.Read(reader, binary.LittleEndian, &msg)
|
||||||
|
@ -358,10 +384,12 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// consume initiation
|
// consume initiation
|
||||||
|
|
||||||
peer := device.ConsumeMessageInitiation(&msg)
|
peer := device.ConsumeMessageInitiation(&msg)
|
||||||
if peer == nil {
|
if peer == nil {
|
||||||
device.log.Verbosef("Received invalid initiation message from %s", elem.endpoint.DstToString())
|
device.log.Verbosef(
|
||||||
|
"Received invalid initiation message from %s",
|
||||||
|
elem.endpoint.DstToString(),
|
||||||
|
)
|
||||||
goto skip
|
goto skip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +422,10 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
|
|
||||||
peer := device.ConsumeMessageResponse(&msg)
|
peer := device.ConsumeMessageResponse(&msg)
|
||||||
if peer == nil {
|
if peer == nil {
|
||||||
device.log.Verbosef("Received invalid response message from %s", elem.endpoint.DstToString())
|
device.log.Verbosef(
|
||||||
|
"Received invalid response message from %s",
|
||||||
|
elem.endpoint.DstToString(),
|
||||||
|
)
|
||||||
goto skip
|
goto skip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +445,11 @@ func (device *Device) RoutineHandshake(id int) {
|
||||||
err = peer.BeginSymmetricSession()
|
err = peer.BeginSymmetricSession()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
device.log.Errorf("%v - Failed to derive keypair: %v", peer, err)
|
device.log.Errorf(
|
||||||
|
"%v - Failed to derive keypair: %v",
|
||||||
|
peer,
|
||||||
|
err,
|
||||||
|
)
|
||||||
goto skip
|
goto skip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +483,10 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !elem.keypair.replayFilter.ValidateCounter(elem.counter, RejectAfterMessages) {
|
if !elem.keypair.replayFilter.ValidateCounter(
|
||||||
|
elem.counter,
|
||||||
|
RejectAfterMessages,
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,13 +513,17 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||||
}
|
}
|
||||||
field := elem.packet[IPv4offsetTotalLength : IPv4offsetTotalLength+2]
|
field := elem.packet[IPv4offsetTotalLength : IPv4offsetTotalLength+2]
|
||||||
length := binary.BigEndian.Uint16(field)
|
length := binary.BigEndian.Uint16(field)
|
||||||
if int(length) > len(elem.packet) || int(length) < ipv4.HeaderLen {
|
if int(length) > len(elem.packet) ||
|
||||||
|
int(length) < ipv4.HeaderLen {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
elem.packet = elem.packet[:length]
|
elem.packet = elem.packet[:length]
|
||||||
src := elem.packet[IPv4offsetSrc : IPv4offsetSrc+net.IPv4len]
|
src := elem.packet[IPv4offsetSrc : IPv4offsetSrc+net.IPv4len]
|
||||||
if device.allowedips.Lookup(src) != peer {
|
if device.allowedips.Lookup(src) != peer {
|
||||||
device.log.Verbosef("IPv4 packet with disallowed source address from %v", peer)
|
device.log.Verbosef(
|
||||||
|
"IPv4 packet with disallowed source address from %v",
|
||||||
|
peer,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,21 +540,36 @@ func (peer *Peer) RoutineSequentialReceiver(maxBatchSize int) {
|
||||||
elem.packet = elem.packet[:length]
|
elem.packet = elem.packet[:length]
|
||||||
src := elem.packet[IPv6offsetSrc : IPv6offsetSrc+net.IPv6len]
|
src := elem.packet[IPv6offsetSrc : IPv6offsetSrc+net.IPv6len]
|
||||||
if device.allowedips.Lookup(src) != peer {
|
if device.allowedips.Lookup(src) != peer {
|
||||||
device.log.Verbosef("IPv6 packet with disallowed source address from %v", peer)
|
device.log.Verbosef(
|
||||||
|
"IPv6 packet with disallowed source address from %v",
|
||||||
|
peer,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
device.log.Verbosef("Packet with invalid IP version from %v", peer)
|
device.log.Verbosef(
|
||||||
|
"Packet with invalid IP version from %v",
|
||||||
|
peer,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
bufs = append(bufs, elem.buffer[:MessageTransportOffsetContent+len(elem.packet)])
|
bufs = append(
|
||||||
|
bufs,
|
||||||
|
elem.buffer[:MessageTransportOffsetContent+len(elem.packet)],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if len(bufs) > 0 {
|
if len(bufs) > 0 {
|
||||||
_, err := device.tun.device.Write(bufs, MessageTransportOffsetContent)
|
_, err := device.tun.device.Write(
|
||||||
|
bufs,
|
||||||
|
MessageTransportOffsetContent,
|
||||||
|
)
|
||||||
if err != nil && !device.isClosed() {
|
if err != nil && !device.isClosed() {
|
||||||
device.log.Errorf("Failed to write packets to TUN device: %v", err)
|
device.log.Errorf(
|
||||||
|
"Failed to write packets to TUN device: %v",
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, elem := range *elems {
|
for _, elem := range *elems {
|
||||||
|
|
134
device/send.go
134
device/send.go
|
@ -9,6 +9,8 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -17,6 +19,7 @@ import (
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
|
"golang.zx2c4.com/wireguard/cfg"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -116,22 +119,47 @@ func (peer *Peer) SendHandshakeInitiation(isRetry bool) error {
|
||||||
|
|
||||||
msg, err := peer.device.CreateMessageInitiation(peer)
|
msg, err := peer.device.CreateMessageInitiation(peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.device.log.Errorf("%v - Failed to create initiation message: %v", peer, err)
|
peer.device.log.Errorf(
|
||||||
|
"%v - Failed to create initiation message: %v",
|
||||||
|
peer,
|
||||||
|
err,
|
||||||
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// so only packet processed for cookie generation
|
||||||
|
var junkedHeader []byte
|
||||||
|
if cfg.IsAdvancedSecurityOn() {
|
||||||
|
err = peer.sendJunkPackets()
|
||||||
|
if err != nil {
|
||||||
|
peer.device.log.Errorf("%v - %v", peer, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var buf [cfg.InitPacketJunkSize]byte
|
||||||
|
writer := bytes.NewBuffer(buf[:0])
|
||||||
|
err = appendJunk(writer, cfg.InitPacketJunkSize)
|
||||||
|
if err != nil {
|
||||||
|
peer.device.log.Errorf("%v - %v", peer, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
junkedHeader = writer.Bytes()
|
||||||
|
}
|
||||||
var buf [MessageInitiationSize]byte
|
var buf [MessageInitiationSize]byte
|
||||||
writer := bytes.NewBuffer(buf[:0])
|
writer := bytes.NewBuffer(buf[:0])
|
||||||
binary.Write(writer, binary.LittleEndian, msg)
|
binary.Write(writer, binary.LittleEndian, msg)
|
||||||
packet := writer.Bytes()
|
packet := writer.Bytes()
|
||||||
peer.cookieGenerator.AddMacs(packet)
|
peer.cookieGenerator.AddMacs(packet)
|
||||||
|
junkedHeader = append(junkedHeader, packet...)
|
||||||
|
|
||||||
peer.timersAnyAuthenticatedPacketTraversal()
|
peer.timersAnyAuthenticatedPacketTraversal()
|
||||||
peer.timersAnyAuthenticatedPacketSent()
|
peer.timersAnyAuthenticatedPacketSent()
|
||||||
|
|
||||||
err = peer.SendBuffers([][]byte{packet})
|
err = peer.SendBuffers([][]byte{junkedHeader})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.device.log.Errorf("%v - Failed to send handshake initiation: %v", peer, err)
|
peer.device.log.Errorf(
|
||||||
|
"%v - Failed to send handshake initiation: %v",
|
||||||
|
peer,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
peer.timersHandshakeInitiated()
|
peer.timersHandshakeInitiated()
|
||||||
|
|
||||||
|
@ -147,15 +175,31 @@ func (peer *Peer) SendHandshakeResponse() error {
|
||||||
|
|
||||||
response, err := peer.device.CreateMessageResponse(peer)
|
response, err := peer.device.CreateMessageResponse(peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.device.log.Errorf("%v - Failed to create response message: %v", peer, err)
|
peer.device.log.Errorf(
|
||||||
|
"%v - Failed to create response message: %v",
|
||||||
|
peer,
|
||||||
|
err,
|
||||||
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
var junkedHeader []byte
|
||||||
|
if cfg.IsAdvancedSecurityOn() {
|
||||||
|
var buf [cfg.ResponsePacketJunkSize]byte
|
||||||
|
writer := bytes.NewBuffer(buf[:0])
|
||||||
|
err = appendJunk(writer, cfg.ResponsePacketJunkSize)
|
||||||
|
if err != nil {
|
||||||
|
peer.device.log.Errorf("%v - %v", peer, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
junkedHeader = writer.Bytes()
|
||||||
|
}
|
||||||
var buf [MessageResponseSize]byte
|
var buf [MessageResponseSize]byte
|
||||||
writer := bytes.NewBuffer(buf[:0])
|
writer := bytes.NewBuffer(buf[:0])
|
||||||
|
|
||||||
binary.Write(writer, binary.LittleEndian, response)
|
binary.Write(writer, binary.LittleEndian, response)
|
||||||
packet := writer.Bytes()
|
packet := writer.Bytes()
|
||||||
peer.cookieGenerator.AddMacs(packet)
|
peer.cookieGenerator.AddMacs(packet)
|
||||||
|
junkedHeader = append(junkedHeader, packet...)
|
||||||
|
|
||||||
err = peer.BeginSymmetricSession()
|
err = peer.BeginSymmetricSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -168,18 +212,31 @@ func (peer *Peer) SendHandshakeResponse() error {
|
||||||
peer.timersAnyAuthenticatedPacketSent()
|
peer.timersAnyAuthenticatedPacketSent()
|
||||||
|
|
||||||
// TODO: allocation could be avoided
|
// TODO: allocation could be avoided
|
||||||
err = peer.SendBuffers([][]byte{packet})
|
err = peer.SendBuffers([][]byte{junkedHeader})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.device.log.Errorf("%v - Failed to send handshake response: %v", peer, err)
|
peer.device.log.Errorf(
|
||||||
|
"%v - Failed to send handshake response: %v",
|
||||||
|
peer,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) SendHandshakeCookie(initiatingElem *QueueHandshakeElement) error {
|
func (device *Device) SendHandshakeCookie(
|
||||||
device.log.Verbosef("Sending cookie response for denied handshake message for %v", initiatingElem.endpoint.DstToString())
|
initiatingElem *QueueHandshakeElement,
|
||||||
|
) error {
|
||||||
|
device.log.Verbosef(
|
||||||
|
"Sending cookie response for denied handshake message for %v",
|
||||||
|
initiatingElem.endpoint.DstToString(),
|
||||||
|
)
|
||||||
|
|
||||||
sender := binary.LittleEndian.Uint32(initiatingElem.packet[4:8])
|
sender := binary.LittleEndian.Uint32(initiatingElem.packet[4:8])
|
||||||
reply, err := device.cookieChecker.CreateReply(initiatingElem.packet, sender, initiatingElem.endpoint.DstToBytes())
|
reply, err := device.cookieChecker.CreateReply(
|
||||||
|
initiatingElem.packet,
|
||||||
|
sender,
|
||||||
|
initiatingElem.endpoint.DstToBytes(),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
device.log.Errorf("Failed to create cookie reply: %v", err)
|
device.log.Errorf("Failed to create cookie reply: %v", err)
|
||||||
return err
|
return err
|
||||||
|
@ -199,7 +256,8 @@ func (peer *Peer) keepKeyFreshSending() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nonce := keypair.sendNonce.Load()
|
nonce := keypair.sendNonce.Load()
|
||||||
if nonce > RekeyAfterMessages || (keypair.isInitiator && time.Since(keypair.created) > RekeyAfterTime) {
|
if nonce > RekeyAfterMessages ||
|
||||||
|
(keypair.isInitiator && time.Since(keypair.created) > RekeyAfterTime) {
|
||||||
peer.SendHandshakeInitiation(false)
|
peer.SendHandshakeInitiation(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,12 +360,18 @@ func (device *Device) RoutineReadFromTUN() {
|
||||||
// TODO: record stat for this
|
// TODO: record stat for this
|
||||||
// This will happen if MSS is surprisingly small (< 576)
|
// This will happen if MSS is surprisingly small (< 576)
|
||||||
// coincident with reasonably high throughput.
|
// coincident with reasonably high throughput.
|
||||||
device.log.Verbosef("Dropped some packets from multi-segment read: %v", readErr)
|
device.log.Verbosef(
|
||||||
|
"Dropped some packets from multi-segment read: %v",
|
||||||
|
readErr,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !device.isClosed() {
|
if !device.isClosed() {
|
||||||
if !errors.Is(readErr, os.ErrClosed) {
|
if !errors.Is(readErr, os.ErrClosed) {
|
||||||
device.log.Errorf("Failed to read packet from TUN device: %v", readErr)
|
device.log.Errorf(
|
||||||
|
"Failed to read packet from TUN device: %v",
|
||||||
|
readErr,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
go device.Close()
|
go device.Close()
|
||||||
}
|
}
|
||||||
|
@ -342,7 +406,8 @@ top:
|
||||||
}
|
}
|
||||||
|
|
||||||
keypair := peer.keypairs.Current()
|
keypair := peer.keypairs.Current()
|
||||||
if keypair == nil || keypair.sendNonce.Load() >= RejectAfterMessages || time.Since(keypair.created) >= RejectAfterTime {
|
if keypair == nil || keypair.sendNonce.Load() >= RejectAfterMessages ||
|
||||||
|
time.Since(keypair.created) >= RejectAfterTime {
|
||||||
peer.SendHandshakeInitiation(false)
|
peer.SendHandshakeInitiation(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -373,7 +438,9 @@ top:
|
||||||
*elems = (*elems)[:i]
|
*elems = (*elems)[:i]
|
||||||
|
|
||||||
if elemsOOO != nil {
|
if elemsOOO != nil {
|
||||||
peer.StagePackets(elemsOOO) // XXX: Out of order, but we can't front-load go chans
|
peer.StagePackets(
|
||||||
|
elemsOOO,
|
||||||
|
) // XXX: Out of order, but we can't front-load go chans
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*elems) == 0 {
|
if len(*elems) == 0 {
|
||||||
|
@ -404,6 +471,31 @@ top:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (peer *Peer) sendJunkPackets() error {
|
||||||
|
junks := make([][]byte, 0, cfg.JunkPacketCount)
|
||||||
|
for i := 0; i < cfg.JunkPacketCount; i++ {
|
||||||
|
packetSize := rand.Intn(
|
||||||
|
cfg.JunkPacketMaxSize-cfg.JunkPacketMinSize,
|
||||||
|
) + cfg.JunkPacketMinSize
|
||||||
|
|
||||||
|
junk, err := randomJunkWithSize(packetSize)
|
||||||
|
if err != nil {
|
||||||
|
peer.device.log.Errorf(
|
||||||
|
"%v - Failed to create junk packet: %v",
|
||||||
|
peer,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
junks = append(junks, junk)
|
||||||
|
}
|
||||||
|
err := peer.SendBuffers(junks)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to send junks: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (peer *Peer) FlushStagedPackets() {
|
func (peer *Peer) FlushStagedPackets() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -459,7 +551,10 @@ func (device *Device) RoutineEncryption(id int) {
|
||||||
binary.LittleEndian.PutUint64(fieldNonce, elem.nonce)
|
binary.LittleEndian.PutUint64(fieldNonce, elem.nonce)
|
||||||
|
|
||||||
// pad content to multiple of 16
|
// pad content to multiple of 16
|
||||||
paddingSize := calculatePaddingSize(len(elem.packet), int(device.tun.mtu.Load()))
|
paddingSize := calculatePaddingSize(
|
||||||
|
len(elem.packet),
|
||||||
|
int(device.tun.mtu.Load()),
|
||||||
|
)
|
||||||
elem.packet = append(elem.packet, paddingZeros[:paddingSize]...)
|
elem.packet = append(elem.packet, paddingZeros[:paddingSize]...)
|
||||||
|
|
||||||
// encrypt content and release to consumer
|
// encrypt content and release to consumer
|
||||||
|
@ -478,7 +573,10 @@ func (device *Device) RoutineEncryption(id int) {
|
||||||
func (peer *Peer) RoutineSequentialSender(maxBatchSize int) {
|
func (peer *Peer) RoutineSequentialSender(maxBatchSize int) {
|
||||||
device := peer.device
|
device := peer.device
|
||||||
defer func() {
|
defer func() {
|
||||||
defer device.log.Verbosef("%v - Routine: sequential sender - stopped", peer)
|
defer device.log.Verbosef(
|
||||||
|
"%v - Routine: sequential sender - stopped",
|
||||||
|
peer,
|
||||||
|
)
|
||||||
peer.stopping.Done()
|
peer.stopping.Done()
|
||||||
}()
|
}()
|
||||||
device.log.Verbosef("%v - Routine: sequential sender - started", peer)
|
device.log.Verbosef("%v - Routine: sequential sender - started", peer)
|
||||||
|
|
25
device/util.go
Normal file
25
device/util.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package device
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
crand "crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func appendJunk(writer *bytes.Buffer, size int) error {
|
||||||
|
headerJunk, err := randomJunkWithSize(size)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create header junk: %v", err)
|
||||||
|
}
|
||||||
|
_, err = writer.Write(headerJunk)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to write header junk: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomJunkWithSize(size int) ([]byte, error) {
|
||||||
|
junk := make([]byte, size)
|
||||||
|
_, err := crand.Read(junk)
|
||||||
|
return junk, err
|
||||||
|
}
|
29
device/util_test.go
Normal file
29
device/util_test.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package device
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.zx2c4.com/wireguard/cfg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_randomJunktWithSize(t *testing.T) {
|
||||||
|
junk, err := randomJunkWithSize(30)
|
||||||
|
fmt.Println(string(junk), len(junk), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_appendJunk(t *testing.T) {
|
||||||
|
t.Run("", func(t *testing.T) {
|
||||||
|
s := "apple"
|
||||||
|
buffer := bytes.NewBuffer([]byte(s))
|
||||||
|
err := appendJunk(buffer, 30)
|
||||||
|
if err != nil &&
|
||||||
|
buffer.Len() != len(s)+int(cfg.InitPacketJunkSize) {
|
||||||
|
t.Errorf("appendWithJunk() size don't match")
|
||||||
|
}
|
||||||
|
read := make([]byte, 50)
|
||||||
|
buffer.Read(read)
|
||||||
|
fmt.Println(string(read))
|
||||||
|
})
|
||||||
|
}
|
2
go.mod
2
go.mod
|
@ -3,10 +3,12 @@ module golang.zx2c4.com/wireguard
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/juju/errors v1.0.0
|
||||||
golang.org/x/crypto v0.6.0
|
golang.org/x/crypto v0.6.0
|
||||||
golang.org/x/net v0.7.0
|
golang.org/x/net v0.7.0
|
||||||
golang.org/x/sys v0.5.1-0.20230222185716-a3b23cc77e89
|
golang.org/x/sys v0.5.1-0.20230222185716-a3b23cc77e89
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0
|
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -1,5 +1,9 @@
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||||
|
github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM=
|
||||||
|
github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8=
|
||||||
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
|
@ -10,5 +14,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqG
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0 h1:Wobr37noukisGxpKo5jAsLREcpj61RxrWYzD8uwveOY=
|
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0 h1:Wobr37noukisGxpKo5jAsLREcpj61RxrWYzD8uwveOY=
|
||||||
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0/go.mod h1:Dn5idtptoW1dIos9U6A2rpebLs/MtTwFacjKb8jLdQA=
|
gvisor.dev/gvisor v0.0.0-20221203005347-703fd9b7fbc0/go.mod h1:Dn5idtptoW1dIos9U6A2rpebLs/MtTwFacjKb8jLdQA=
|
||||||
|
|
15
util/cfgGenerator/cfg_values.txt
Normal file
15
util/cfgGenerator/cfg_values.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// THIS IS A GENERATED FILE; ANY MODIFICATION WILL BE LOST
|
||||||
|
|
||||||
|
package cfg
|
||||||
|
|
||||||
|
const JunkPacketCount int = {{.JunkPacketCount}}
|
||||||
|
const JunkPacketMinSize int = {{.JunkPacketMinSize}}
|
||||||
|
const JunkPacketMaxSize int = {{.JunkPacketMaxSize}}
|
||||||
|
const InitPacketJunkSize int = {{.InitPacketJunkSize}}
|
||||||
|
const ResponsePacketJunkSize int = {{.ResponsePacketJunkSize}}
|
||||||
|
const UnderLoadPacketJunkSize int = {{.UnderLoadPacketJunkSize}}
|
||||||
|
const TransportPacketJunkSize int = {{.TransportPacketJunkSize}}
|
||||||
|
const InitPacketMagicHeader uint32 = {{.InitPacketMagicHeader}}
|
||||||
|
const ResponsePacketMagicHeader uint32 = {{.ResponsePacketMagicHeader}}
|
||||||
|
const UnderloadPacketMagicHeader uint32 = {{.UnderloadPacketMagicHeader}}
|
||||||
|
const TransportPacketMagicHeader uint32 = {{.TransportPacketMagicHeader}}
|
43
util/cfgGenerator/generator.go
Normal file
43
util/cfgGenerator/generator.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"golang.zx2c4.com/wireguard/util/cfgGenerator/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfgName := "default"
|
||||||
|
if len(os.Args) != 1 {
|
||||||
|
cfgName = os.Args[1]
|
||||||
|
} else {
|
||||||
|
fmt.Println("WARNING; config name omited; using default")
|
||||||
|
}
|
||||||
|
|
||||||
|
ex, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
mainPath := filepath.Dir(ex)
|
||||||
|
cfgPath := mainPath + "/cfg/"
|
||||||
|
cfgFilePath := cfgPath + "settings/" + cfgName + ".yml"
|
||||||
|
|
||||||
|
cfgTmpl, err := template.ParseFiles(
|
||||||
|
mainPath + "/util/cfgGenerator/cfg_values.txt",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
cfg, err := config.NewFromFilename(cfgFilePath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
f, _ := os.Create(cfgPath + "cfg_values.go")
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
cfgTmpl.Execute(f, *cfg)
|
||||||
|
f.Sync()
|
||||||
|
}
|
58
util/cfgGenerator/internal/config/config.go
Normal file
58
util/cfgGenerator/internal/config/config.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
JunkPacketCount int `yaml:"junk_packet_count"`
|
||||||
|
JunkPacketMinSize int `yaml:"junk_packet_min_size"`
|
||||||
|
JunkPacketMaxSize int `yaml:"junk_packet_max_size"`
|
||||||
|
InitPacketJunkSize int `yaml:"init_packet_junk_size"`
|
||||||
|
ResponsePacketJunkSize int `yaml:"response_packet_junk_size"`
|
||||||
|
UnderLoadPacketJunkSize int `yaml:"underload_packet_junk_size"`
|
||||||
|
TransportPacketJunkSize int `yaml:"transport_packet_junk_size"`
|
||||||
|
InitPacketMagicHeader uint32 `yaml:"init_packet_magic_header"`
|
||||||
|
ResponsePacketMagicHeader uint32 `yaml:"response_packet_magic_header"`
|
||||||
|
UnderloadPacketMagicHeader uint32 `yaml:"underload_packet_magic_header"`
|
||||||
|
TransportPacketMagicHeader uint32 `yaml:"transport_packet_magic_header"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new CW from a file by the given name
|
||||||
|
func New(name string) (*config, error) {
|
||||||
|
return NewFromFilename(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFromFilename creates a new CW from a file by the given filename
|
||||||
|
func NewFromFilename(filename string) (*config, error) {
|
||||||
|
data, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewFromRaw(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFromRaw creates a new CW by unmarshaling the given raw data
|
||||||
|
func NewFromRaw(raw []byte) (*config, error) {
|
||||||
|
cfg := &config{}
|
||||||
|
if err := yaml.Unmarshal(raw, cfg); err != nil {
|
||||||
|
return nil, errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// String can't be defined on a value receiver here because of the mutex
|
||||||
|
func (c *config) String() string {
|
||||||
|
raw, err := yaml.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(raw)
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue