diff --git a/pkg/wireguard/packetlogger.go b/pkg/wireguard/packetlogger.go index 2aa03ec..509f3cb 100644 --- a/pkg/wireguard/packetlogger.go +++ b/pkg/wireguard/packetlogger.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "net/http" + "os" "path" "runtime" "strconv" @@ -18,6 +19,7 @@ import ( "github.com/in4it/wireguard-server/pkg/logging" "github.com/in4it/wireguard-server/pkg/storage" "github.com/packetcap/go-pcap" + "golang.org/x/sys/unix" ) func RunPacketLogger(storage storage.Iface, clientCache *ClientCache) { @@ -30,11 +32,20 @@ func RunPacketLogger(storage storage.Iface, clientCache *ClientCache) { logging.ErrorLog(fmt.Errorf("can't start packet inspector: %s", err)) return } + i := 0 for { err := readPacket(storage, handle, clientCache) if err != nil { logging.DebugLog(fmt.Errorf("readPacket error: %s", err)) } + if i%1000 == 0 { + if err := checkDiskSpace(); err != nil { + logging.ErrorLog(fmt.Errorf("disk space error: %s", err)) + return + } + i = 0 + } + i++ } } func readPacket(storage storage.Iface, handle *pcap.Handle, clientCache *ClientCache) error { @@ -94,7 +105,6 @@ func parsePacket(storage storage.Iface, data []byte, clientCache *ClientCache) e switch tcpPacket.DstPort { case 80: if tcpPacket.DstPort == 80 { - //fmt.Printf("payload: %s", tcpPacket.LayerContents()) appLayer := packet.ApplicationLayer() if appLayer != nil { req, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(appLayer.Payload()))) @@ -218,7 +228,6 @@ func parseTLSExtensionSNI(data []byte) []byte { if serverNameExtensionLength > 0 && entryType == 0 && len(data) > 8 { // 0 = DNS hostname hostnameLength := binary.BigEndian.Uint16(data[7:9]) - fmt.Printf("extensionType: %d length: %d; slice: %d\n", extensionType, serverNameExtensionLength, 9+hostnameLength) if len(data) > int(8+hostnameLength) { return data[9 : 9+hostnameLength] } @@ -228,3 +237,22 @@ func parseTLSExtensionSNI(data []byte) []byte { } return nil } + +func checkDiskSpace() error { + var stat unix.Statfs_t + + wd, err := os.Getwd() + if err != nil { + fmt.Printf("cannot get cwd: %s", err) + } + unix.Statfs(wd, &stat) + if stat.Blocks*uint64(stat.Bsize) == 0 { + return fmt.Errorf("no blocks available") + } + freeDiskSpace := float64(stat.Bfree) / float64(stat.Blocks) + if freeDiskSpace < 0.10 { + return fmt.Errorf("not enough disk free disk space: %f", freeDiskSpace) + } + + return nil +} diff --git a/pkg/wireguard/packetlogger_test.go b/pkg/wireguard/packetlogger_test.go index fd427d5..6c0c000 100644 --- a/pkg/wireguard/packetlogger_test.go +++ b/pkg/wireguard/packetlogger_test.go @@ -74,19 +74,70 @@ func TestParsePacket(t *testing.T) { } } +func TestParsePacketSNI(t *testing.T) { + storage := &testingmocks.MockMemoryStorage{} + clientCache := &ClientCache{ + Addresses: []ClientCacheAddresses{ + { + Address: net.IPNet{ + IP: net.ParseIP("10.189.184.2"), + Mask: net.IPMask(net.ParseIP("255.255.255.255").To4()), + }, + ClientID: "1-2-3-4-1", + }, + { + Address: net.IPNet{ + IP: net.ParseIP("10.189.184.3"), + Mask: net.IPMask(net.ParseIP("255.255.255.255").To4()), + }, + ClientID: "1-2-3-5-1", + }, + }, + } + input := []string{ + `450000d100004000400682160abdb80240e9b468ec5001bb4f71ed891a93673d8018080468f400000101080a1329f7772c5410131603010098010000940301f1d62f57f05cc00fc8fb984e7fc381a26adc301ec143b9bab6d36f3f1b15c97200002ec014c00a0039ff850088008100350084c013c00900330045002f0041c011c00700050004c012c0080016000a00ff0100003d00000013001100000e7777772e676f6f676c652e636f6d000b00020100000a000a0008001d0017001800190010000e000c02683208687474702f312e31`, + } + now := time.Now() + for _, s := range input { + + data, err := hex.DecodeString(s) + if err != nil { + t.Fatalf("hex decode error: %s", err) + } + err = parsePacket(storage, data, clientCache) + if err != nil { + t.Fatalf("parse error: %s", err) + } + } + + out, err := storage.ReadFile(path.Join(VPN_STATS_DIR, "ip-"+now.Format("2006-01-02.log"))) + if err != nil { + t.Fatalf("read file error: %s", err) + } + if !strings.Contains(string(out), `,https,10.189.184.2,64.233.180.104,60496,443,www.google.com`) { + t.Fatalf("unexpected output. Expected https record") + } +} + func TestParseTLSExtensionSNI(t *testing.T) { input := []string{ + "00000013001100000e7777772e676f6f676c652e636f6d000b00020100000a000a0008001d0017001800190010000e000c02683208687474702f312e31", "00000018001600001376706e2d7365727665722e696e3469742e696f", "00000018001600001376706e2d7365727665722e696e3469742e696f000b00020100000a000a0008001d001700180019000d00180016080606010603080505010503080404010403020102030010000e000c02683208687474702f312e31", } - for _, s := range input { + match := []string{ + "www.google.com", + "vpn-server.in4it.io", + "vpn-server.in4it.io", + } + for k, s := range input { data, err := hex.DecodeString(s) if err != nil { t.Fatalf("hex decode error: %s", err) } if sni := parseTLSExtensionSNI(data); sni != nil { - if string(sni) != "vpn-server.in4it.io" { + if string(sni) != match[k] { t.Fatalf("got SNI, but expected different hostname. Got: %s", sni) } } else { @@ -111,3 +162,10 @@ func TestParseTLSExtensionSNINoMatch(t *testing.T) { } } } + +func TestCheckDiskSpace(t *testing.T) { + err := checkDiskSpace() + if err != nil { + t.Fatalf("disk space error: %s", err) + } +}