Skip to content

Commit

Permalink
🐙 adding advanced IP packet debugging
Browse files Browse the repository at this point in the history
  • Loading branch information
smolgroot committed Aug 22, 2024
1 parent f8066f2 commit cf872b5
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 18 deletions.
51 changes: 50 additions & 1 deletion pkg/utils/ip.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package utils

import (
"encoding/binary"
"fmt"
"log"
"net"
)

Expand Down Expand Up @@ -34,4 +36,51 @@ func IsPublicIP(ipStr string) bool {
}

return true // IP is public
}
}

func PrettyPrintIPHeader(packet []byte, level string) {
color := Cyan
switch level {
case "DEBUG":
color = Orange
case "ERROR":
color = Red
default:
color = Cyan
}
if len(packet) < 20 {
log.Println(Orange, "Packet too short", Reset)
return
}

version := packet[0] >> 4
ihl := packet[0] & 0x0F
tos := packet[1]
totalLength := binary.BigEndian.Uint16(packet[2:4])
identification := binary.BigEndian.Uint16(packet[4:6])
flags := packet[6] >> 5
fragmentOffset := binary.BigEndian.Uint16(packet[6:8]) & 0x1FFF
ttl := packet[8]
protocol := GetProtocolById(packet[9])
headerChecksum := binary.BigEndian.Uint16(packet[10:12])
sourceAddress := net.IP(packet[12:16])
destinationAddress := net.IP(packet[16:20])

log.Println(color, "IP Header:", Reset)
log.Println(color, "+---------------------+---------------------+", Reset)
log.Println(color, "| Field | Value |", Reset)
log.Println(color, "+---------------------+---------------------+", Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Version", version, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "IHL", ihl, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Type of Service", tos, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Total Length", totalLength, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Identification", identification, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Flags", flags, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Fragment Offset", fragmentOffset, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Time to Live", ttl, Reset)
log.Printf(" %s| %-19s | %v |%s\n", color, "Protocol", protocol, Reset)
log.Printf(" %s| %-19s | %-19d |%s\n", color, "Header Checksum", headerChecksum, Reset)
log.Printf(" %s| %-19s | %-19s |%s\n", color, "Source Address", sourceAddress, Reset)
log.Printf(" %s| %-19s | %-19s |%s\n", color, "Destination Address", destinationAddress, Reset)
log.Println(color, "+---------------------+---------------------+", Reset)
}
63 changes: 63 additions & 0 deletions pkg/utils/test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package utils

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
)

func TestNickname(t *testing.T) {
router := gin.Default()
router.GET("/nickname", Nickname)

w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/nickname", nil)
router.ServeHTTP(w, req)

if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, but got %d", http.StatusOK, w.Code)
}

expected := `{"Nickname":"your-nickname"}`
if w.Body.String() != expected {
t.Errorf("Expected body %s, but got %s", expected, w.Body.String())
}
}

func TestPing(t *testing.T) {
router := gin.Default()
router.GET("/ping", Ping)

w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/ping", nil)
router.ServeHTTP(w, req)

if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, but got %d", http.StatusOK, w.Code)
}

expected := `{"message":"pong"}`
if w.Body.String() != expected {
t.Errorf("Expected body %s, but got %s", expected, w.Body.String())
}
}

func TestOk(t *testing.T) {
router := gin.Default()
router.GET("/", Ok)

w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/", nil)
router.ServeHTTP(w, req)

if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, but got %d", http.StatusOK, w.Code)
}

expected := `{"message":"OK"}`
if w.Body.String() != expected {
t.Errorf("Expected body %s, but got %s", expected, w.Body.String())
}
}
29 changes: 12 additions & 17 deletions pkg/vpn/p2pEndpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/hex"
"fmt"
"log"
"net"
"net/http"
"runtime"
"sync"
Expand Down Expand Up @@ -172,6 +171,7 @@ func Connect(node host.Host, dht *dht.IpfsDHT) gin.HandlerFunc {

// loop to read from the TUN interface and write to the libp2p stream.
doTx := func() {
var i int
packet := make([]byte, MTUSize)
for {
mu.Lock()
Expand All @@ -193,6 +193,8 @@ func Connect(node host.Host, dht *dht.IpfsDHT) gin.HandlerFunc {
// debug
header, _ := ipv4.ParseHeader(packet[:plen])
log.Printf("%vSending to remote: %+v (%+v)%v\n", utils.Green, header, err, utils.Reset)
log.Println(utils.Cyan, "Packet received", i, utils.Reset)
i++
continue
}
}
Expand All @@ -210,7 +212,7 @@ func Connect(node host.Host, dht *dht.IpfsDHT) gin.HandlerFunc {
return gin.HandlerFunc(fn)
}

func doRx(rw *bufio.ReadWriter, mu *sync.Mutex, inter *water.Interface) {
func doRx(rw *bufio.ReadWriter, mu *sync.Mutex, inet *water.Interface) {
packet := make([]byte, MTUSize)
// packetSize := make([]byte, 2)
var i int
Expand All @@ -225,12 +227,17 @@ func doRx(rw *bufio.ReadWriter, mu *sync.Mutex, inter *water.Interface) {
}

// Decode the incoming packet's size from binary.
if len(packet) < 4 {
log.Fatal("packet too short")
}
size := binary.BigEndian.Uint16(packet[2:4])
// size := binary.LittleEndian.Uint16(packetSize)
// log.Println("receiving packet of size", size)
log.Println(utils.Orange, "receiving packet of size", size, packet[2:4], utils.Reset)
if size == 0 {
log.Println(utils.Red, packet, utils.Reset)
log.Println(utils.Red, hex.Dump(packet), utils.Reset)
utils.PrettyPrintIPHeader(packet, "ERROR")
}

// Read in the packet until completion.
Expand All @@ -247,28 +254,16 @@ func doRx(rw *bufio.ReadWriter, mu *sync.Mutex, inter *water.Interface) {
}

log.Println(utils.Orange, "\n"+hex.Dump(packet[:plen]), packet[:plen], plen, size, utils.Reset)
log.Println(utils.Orange, "───────────────────── IP packet ─────────────────────", utils.Reset)
// debug
header, _ := ipv4.ParseHeader(packet[:plen])
log.Printf("%vReading IP packet: %+v (%+v)%v\n", utils.Orange, header, err, utils.Reset)
proto := utils.GetProtocolById(packet[9])
log.Println(utils.Orange, "Packet Size:\t", packet[2:4], utils.Reset)
log.Println(utils.Orange, "Protocol:\t\t", proto, utils.Reset)
src := net.IPv4(packet[12], packet[13], packet[14], packet[15]).String()
log.Println(utils.Orange, "Source:\t\t", src, utils.Reset)
dst := net.IPv4(packet[16], packet[17], packet[18], packet[19]).String()
log.Println(utils.Orange, "Destination:\t", dst, utils.Reset)
log.Println(utils.Orange, "─────────────────────────────────────────────────────", utils.Reset)

utils.PrettyPrintIPHeader(packet, "DEBUG")
if size <= MTUSize && plen != 0 {
mu.Lock()
log.Println(utils.Orange, "mutex locked (writing to tun interface)", utils.Reset)
_, err = inter.Write(packet[:size])
_, err = inet.Write(packet[:size])
mu.Unlock()
log.Println(utils.Orange, "mutex unlocked", utils.Reset)
utils.Check(err)
}
log.Println(utils.Orange, i, utils.Reset)
log.Println(utils.Orange, "Packet written", i, utils.Reset)
i++
}
}

0 comments on commit cf872b5

Please sign in to comment.