Reduce idle CPU (cheap PollUI, binary cache, logbuf cap, DOM fingerprint), speed ping/AWG HostPort, CopyBuffer pool; ship arm64 build and update notes. Co-authored-by: Cursor <cursoragent@cursor.com>
265 lines
6.3 KiB
Go
265 lines
6.3 KiB
Go
package awg
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseINI_AWG20(t *testing.T) {
|
|
raw := `[Interface]
|
|
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|
Address = 10.8.0.2/32
|
|
DNS = 1.1.1.1
|
|
Jc = 4
|
|
Jmin = 40
|
|
Jmax = 70
|
|
H1 = 1
|
|
H2 = 2
|
|
H3 = 3
|
|
H4 = 4
|
|
I1 = <r 128>
|
|
|
|
[Peer]
|
|
PublicKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
|
|
Endpoint = 203.0.113.10:51820
|
|
AllowedIPs = 0.0.0.0/0
|
|
PersistentKeepalive = 25
|
|
`
|
|
c, err := Parse(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Jc != 4 || c.I1 != "<r 128>" || c.Endpoint != "203.0.113.10:51820" {
|
|
t.Fatalf("unexpected conf: %+v", c)
|
|
}
|
|
if !c.IsAWG20() {
|
|
t.Fatal("expected AWG2 markers")
|
|
}
|
|
ipc, err := c.ToIPC()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !containsAll(ipc, "jc=4", "i1=<r 128>", "endpoint=203.0.113.10:51820") {
|
|
t.Fatalf("bad ipc: %s", ipc)
|
|
}
|
|
}
|
|
|
|
func TestParseURI_UserInfoPrivateKey(t *testing.T) {
|
|
priv := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
|
pub := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE="
|
|
raw := "awg://" + priv + "@203.0.113.10:51820/?public_key=" + pub + "&address=10.8.0.2/32&jc=4"
|
|
c, err := Parse(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.PrivateKey != priv {
|
|
t.Fatalf("private key: %q", c.PrivateKey)
|
|
}
|
|
if c.PublicKey != pub {
|
|
t.Fatalf("public key: %q", c.PublicKey)
|
|
}
|
|
if c.Endpoint != "203.0.113.10:51820" {
|
|
t.Fatalf("endpoint: %q", c.Endpoint)
|
|
}
|
|
}
|
|
|
|
func TestParseINI_SpacedKeysAndQuotes(t *testing.T) {
|
|
raw := `Private Key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
|
Address = 10.8.0.2/32
|
|
[Peer]
|
|
Public Key = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE='
|
|
Endpoint = 1.2.3.4:51820
|
|
`
|
|
c, err := Parse(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.PrivateKey == "" || c.PublicKey == "" {
|
|
t.Fatalf("keys missing: %+v", c)
|
|
}
|
|
}
|
|
|
|
func TestParseAmneziaJSON(t *testing.T) {
|
|
raw := `{
|
|
"client_priv_key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
|
"server_pub_key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=",
|
|
"client_ip": "10.8.0.2/32",
|
|
"hostName": "203.0.113.10",
|
|
"port": "51820",
|
|
"Jc": 4,
|
|
"Jmin": 10,
|
|
"Jmax": 50,
|
|
"H1": "1",
|
|
"H2": "2",
|
|
"H3": "3",
|
|
"H4": "4"
|
|
}`
|
|
c, err := Parse(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Endpoint != "203.0.113.10:51820" {
|
|
t.Fatalf("endpoint %q", c.Endpoint)
|
|
}
|
|
if c.Jc != 4 {
|
|
t.Fatalf("jc %d", c.Jc)
|
|
}
|
|
}
|
|
|
|
func TestParseVPNScheme(t *testing.T) {
|
|
inner := `{"client_priv_key":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","server_pub_key":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=","client_ip":"10.8.0.2/32","hostName":"9.9.9.9","port":"51820"}`
|
|
raw := "vpn://" + base64.StdEncoding.EncodeToString([]byte(inner))
|
|
c, err := Parse(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Endpoint != "9.9.9.9:51820" {
|
|
t.Fatalf("endpoint %q", c.Endpoint)
|
|
}
|
|
}
|
|
|
|
func TestDetect(t *testing.T) {
|
|
if !Detect("[Interface]\nPrivateKey = x") {
|
|
t.Fatal("expected detect")
|
|
}
|
|
if !Detect("awg://1.2.3.4:51820/?private_key=a&public_key=b&address=10.0.0.2/32") {
|
|
t.Fatal("expected awg uri detect")
|
|
}
|
|
if !Detect(`{"client_priv_key":"x","server_pub_key":"y"}`) {
|
|
t.Fatal("expected json detect")
|
|
}
|
|
}
|
|
|
|
func TestDecodeKeyURLSafe(t *testing.T) {
|
|
// 32 zero bytes, URL-safe without padding
|
|
raw := base64.RawURLEncoding.EncodeToString(make([]byte, 32))
|
|
b, err := decodeKey(raw)
|
|
if err != nil || len(b) != 32 {
|
|
t.Fatalf("url-safe: %v %d", err, len(b))
|
|
}
|
|
}
|
|
|
|
func TestResolveEndpointPrefersIPv4(t *testing.T) {
|
|
got, err := resolveEndpointWith("peer.example:41421", func(host string) ([]net.IP, error) {
|
|
if host != "peer.example" {
|
|
t.Fatalf("host %q", host)
|
|
}
|
|
return []net.IP{
|
|
net.ParseIP("2001:db8::1"),
|
|
net.ParseIP("203.0.113.44"),
|
|
}, nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != "203.0.113.44:41421" {
|
|
t.Fatalf("got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveEndpointAlreadyIP(t *testing.T) {
|
|
got, err := resolveEndpointWith("203.0.113.10:51820", func(string) ([]net.IP, error) {
|
|
t.Fatal("lookup should not run for IP")
|
|
return nil, nil
|
|
})
|
|
if err != nil || got != "203.0.113.10:51820" {
|
|
t.Fatalf("%q %v", got, err)
|
|
}
|
|
}
|
|
|
|
func TestResolveEndpointDNSError(t *testing.T) {
|
|
_, err := resolveEndpointWith("missing.invalid:41421", func(string) ([]net.IP, error) {
|
|
return nil, &net.DNSError{Err: "no such host", Name: "missing.invalid", IsNotFound: true}
|
|
})
|
|
if err == nil || !stringsContains(err.Error(), "не удалось разрешить DNS") {
|
|
t.Fatalf("expected Russian DNS error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestToIPCResolvesEndpoint(t *testing.T) {
|
|
old := lookupIP
|
|
lookupIP = func(host string) ([]net.IP, error) {
|
|
return []net.IP{net.ParseIP("198.51.100.9")}, nil
|
|
}
|
|
defer func() { lookupIP = old }()
|
|
|
|
c := Conf{
|
|
PrivateKey: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
|
PublicKey: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=",
|
|
Address: []string{"10.8.0.2/32"},
|
|
Endpoint: "peer.example:41421",
|
|
}
|
|
ipc, err := c.ToIPC()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !stringsContains(ipc, "endpoint=198.51.100.9:41421") {
|
|
t.Fatalf("ipc missing resolved endpoint: %s", ipc)
|
|
}
|
|
}
|
|
|
|
func TestConfResolveEndpointMutates(t *testing.T) {
|
|
old := lookupIP
|
|
lookupIP = func(string) ([]net.IP, error) {
|
|
return []net.IP{net.ParseIP("198.51.100.1")}, nil
|
|
}
|
|
defer func() { lookupIP = old }()
|
|
|
|
c := Conf{Endpoint: "host.example:41421"}
|
|
if err := c.ResolveEndpoint(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Endpoint != "198.51.100.1:41421" {
|
|
t.Fatalf("endpoint %q", c.Endpoint)
|
|
}
|
|
}
|
|
|
|
func containsAll(s string, parts ...string) bool {
|
|
for _, p := range parts {
|
|
if !stringsContains(s, p) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func stringsContains(s, sub string) bool {
|
|
return len(sub) == 0 || (len(s) >= len(sub) && indexOf(s, sub) >= 0)
|
|
}
|
|
|
|
func indexOf(s, sub string) int {
|
|
for i := 0; i+len(sub) <= len(s); i++ {
|
|
if s[i:i+len(sub)] == sub {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func TestHostPortLightINI(t *testing.T) {
|
|
raw := `[Interface]
|
|
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|
Address = 10.8.0.2/32
|
|
|
|
[Peer]
|
|
PublicKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
|
|
Endpoint = 203.0.113.10:51820
|
|
AllowedIPs = 0.0.0.0/0
|
|
`
|
|
h, p, err := HostPort(raw)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if h != "203.0.113.10" || p != "51820" {
|
|
t.Fatalf("got %s:%s", h, p)
|
|
}
|
|
h2, p2, err := HostPort("awg://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=@9.9.9.9:41421")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if h2 != "9.9.9.9" || p2 != "41421" {
|
|
t.Fatalf("uri got %s:%s", h2, p2)
|
|
}
|
|
}
|