diff --git a/.docker/go/Dockerfile b/.docker/go/Dockerfile
index a0e4506..11e2b52 100644
--- a/.docker/go/Dockerfile
+++ b/.docker/go/Dockerfile
@@ -2,4 +2,4 @@ FROM golang:1.19
ENV GO111MODULE on
-RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y iproute2 iputils-ping dnsutils traceroute iperf3 lsof tcpdump wireshark vim
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y iproute2 iputils-ping dnsutils iperf3 vim tcpdump lsof
diff --git a/README.md b/README.md
index 9b00809..6e232ba 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,129 @@
-# 📣 echoman: simple echo server
+# 🐶 echoman: Simple echo server using Rawsocket
-## 🌱 Overview
-- This is a simple tool where a client generates packets over TCP/IP and sends them to a server.
-- The echo server echoes data by swapping src/dst L3 address and L4 port number. (However, some parameters such as TypeCode and CheckSum are recalculated.)
+## 🌱 Overview
+- これはTCP/IPの上でClientがパケットを生成してServerへ送信するだけの簡単なツールです
+- Serverはsrc/dst L2,L3アドレス, L4ポート番号を入れ替えてデータをechoします(ただし、TypeCodeやCheckSumなどの一部パラメータは再計算する)
+- Rawsocketを使用してL2レベル(`syscall.ETH_P_IP`)でパケットを操作
+ - **LayersType: `LayerTypeEthernet`**
-## ✏️ Documents
-- [Information: Network design](./docs/01_information.md)
-- [Application: An application that communicates over the overlay network](./docs/02_application.md)
-- [Usage: How to start echoman](./docs/03_usage.md)
-- [Appendix: About sockets](./docs/04_appendix.md)
+## ⚡️ Generating socket descriptors
+### Socket functions
+
+
+### Used function
+| args | syscall |
+| :--- | :---: |
+| Domain | `AF_PACKET` |
+| Type | `SOCK_RAW` |
+| Protocols | `ETH_P_IP` |
+
+```go
+### 送信ソケットの生成
+func etherSendSock(intfIndex *net.Interface) (int, error) {
+ fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_IP)))
+ if err != nil {
+ return -1, err
+ }
+
+ addr := syscall.SockaddrLinklayer{
+ Protocol: htons(syscall.ETH_P_ALL),
+ Ifindex: intfIndex.Index,
+ }
+
+ if err := syscall.Bind(fd, &addr); err != nil {
+ return -1, err
+ }
+
+ return fd, nil
+}
+
+### 受信ソケットの生成
+func etherRecvSock(intfIndex *net.Interface) (int, error) {
+ fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_IP)))
+ if err != nil {
+ return -1, err
+ }
+
+ addr := syscall.SockaddrLinklayer{
+ Protocol: htons(syscall.ETH_P_ALL),
+ Ifindex: intfIndex.Index,
+ }
+ if err := syscall.Bind(fd, &addr); err != nil {
+ return -1, err
+ }
+
+ // Received in promiscuous mode
+ if err := syscall.SetLsfPromisc(intfIndex.Name, true); err != nil {
+ return -1, err
+ }
+
+ return fd, nil
+}
+
+### Ethernetパケット(L2~)の送信
+func SendEtherPacket(fd int, b []byte) error {
+ if _, err := syscall.Write(fd, b); err != nil {
+ return err
+ }
+
+ return nil
+}
+```
+
+## 🤝 Requirement
+- **⚠️WARNING**:https://docs.docker.com/desktop/previous-versions/3.x-mac/#new-9
+
+> First version of docker compose (as an alternative to the existing docker-compose). Supports some basic commands but not the complete functionality of docker-compose yet.
+
+| Languages / Frameworks | Version |
+| :--- | ---: |
+| Golang | 1.19.1 |
+| Docker Desktop | 4.12.0 |
+| docker | 20.10.17 |
+| docker-compose | 1.29.2 |
+
+## 🚀 Usage
+```sh
+### envをコピー
+$ cp server/.env{.sample,}
+$ cp client/.env{.sample,}
+
+### .envの中身を環境に合わせて書き換える
+※注意: Docker networkではMACアドレスはランダムに生成されます
+
+### docker-composeを起動
+$ make up
+
+### 実行
+---
+### 1枚目のTerminal: Echoman server を起動
+$ make exec/server
+# make run
+
+### 2枚目のTerminal: Echoman client を起動
+$ make exec/client
+# make run
+---
+
+### Echoman clientはデフォルトでUDPを喋ります
+-> .env を編集することで生成するパケットタイプを切り替える
+PACKET_TYPE=[パケットタイプ]
+```
+| PacketType | Env Value |
+| :--- | :---: |
+| ICMPv4 | `ICMPV4` |
+| UDPv4 | `UDPV4` |
+
+## 📖 Default Information
+
+| Device | Information |
+| :--- | ---: |
+| Echoman Server IPv4 address | `10.0.3.95` |
+| Echoman Server Port number | `30005` |
+| Echoman Client IPv4 address | `10.0.3.96` |
+| Echoman Client Port number | `30006` |
## 📚 References
-- [RFC 792 - Internet Control Message Protocol](https://www.rfc-editor.org/rfc/rfc792)
-- [RFC 768 - User Datagram Protocol](https://www.rfc-editor.org/rfc/rfc768)
-- [Universal TUN/TAP device driver](https://docs.kernel.org/networking/tuntap.html)
-- [Checksum calculation](https://o21o21.hatenablog.jp/entry/2019/01/31/120436)
+- [RFC 792](https://www.rfc-editor.org/rfc/rfc792)
+- [RFC 768](https://www.rfc-editor.org/rfc/rfc768)
+- [Checksum計算](https://o21o21.hatenablog.jp/entry/2019/01/31/120436)
diff --git a/client/.env.sample b/client/.env.sample
index de5370f..569734b 100644
--- a/client/.env.sample
+++ b/client/.env.sample
@@ -1,15 +1,10 @@
-DEBUG_MODE=true
-VIRTUAL_IP_TYPE=4
-
LOCAL_INTERFACE=eth0
+LOCAL_UDP_PORT=30006
PEER_IPV4_ADDRESS=10.0.3.95
-PEER_IPV6_ADDRESS=fde4:db8::0395
-PEER_UDP_PORT=30000
+PEER_MAC_ADDRESS=02:42:0a:00:03:5f
+PEER_UDP_PORT=30005
-TUN_INTERFACE_NAME=echoman_tun
+PACKET_TYPE=UDPV4
-ECHOMAN_SERVER_IPV4_TUN=198.18.9.10
-ECHOMAN_SERVER_IPV6_TUN=2001:db8:c0ff:ee00:0910:0910:0910:0910
-
-CHROUS_PORT=30910
+DEBUG_MODE=true
diff --git a/client/Makefile b/client/Makefile
index 9dfd672..f0bb7ed 100644
--- a/client/Makefile
+++ b/client/Makefile
@@ -8,8 +8,7 @@ GODOC=$(GOCMD)doc
GOLANGCI=golangci-lint
DUMPCMD=tcpdump
-INTERFACE_REAL=eth0
-INTERFACE_VIRTUAL=echoman_tun
+INTERFACE=eth0
@@ -43,17 +42,11 @@ coverage: ## coverage
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out -o cover.html
-dump-real: ## dump packet
- $(DUMPCMD) -i ${INTERFACE_REAL}
+dump: ## dump packet
+ $(DUMPCMD) -i ${INTERFACE}
-dump-virtual: ## dump packet
- $(DUMPCMD) -i ${INTERFACE_VIRTUAL}
-
-dump-real/out: ## dump packet and output to file
- $(DUMPCMD) -i ${INTERFACE_REAL} -w ./debug/dumpfile-client-real.pcapng
-
-dump-virtual/out: ## dump packet and output to file
- $(DUMPCMD) -i ${INTERFACE_VIRTUAL} -w ./debug/dumpfile-client-virtual.pcapng
+dump/out: ## dump packet and output to file
+ $(DUMPCMD) -i ${INTERFACE} -w ./debug/dumpfile-client.pcapng
listen: ## check listen port
lsof -i -P
diff --git a/client/chorus/generate_request.go b/client/chorus/generate_request.go
deleted file mode 100644
index 70a2187..0000000
--- a/client/chorus/generate_request.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package chorus
-
-import (
- "net"
-
- "github.com/GotoRen/echoman/client/internal/logger"
- "github.com/google/gopacket"
- golayers "github.com/google/gopacket/layers"
-)
-
-// GenerateUDPRequestPacket generates udp request packet.
-func GenerateUDPRequestPacket(srcVIPv4, dstVIPv4 net.IP, chorusPort golayers.UDPPort) ([]byte, error) {
- data := []byte("Ping")
-
- ip := golayers.IPv4{
- Version: 4,
- Protocol: golayers.IPProtocolUDP,
- SrcIP: srcVIPv4,
- DstIP: dstVIPv4,
- }
-
- udp := golayers.UDP{
- SrcPort: chorusPort,
- DstPort: chorusPort,
- }
-
- // calculating checksum
- if err := udp.SetNetworkLayerForChecksum(&ip); err != nil {
- logger.LogErr("udp set error", "error", err)
- return nil, err
- }
-
- options := gopacket.SerializeOptions{
- ComputeChecksums: true,
- FixLengths: true,
- }
-
- buffer := gopacket.NewSerializeBuffer()
-
- if err := gopacket.SerializeLayers(buffer, options,
- &ip,
- &udp,
- gopacket.Payload(data),
- ); err != nil {
- logger.LogErr("Serialize error", "error", err)
- return nil, err
- }
-
- // _Test
- // outgoing := []byte{
- // 0x45, 0x00, 0x00, 0x20,
- // 0x0d, 0x73, 0x00, 0x00,
- // 0x00, 0x11, 0x3c, 0xf2,
- // 0xc6, 0x12, 0xdb, 0x39,
- // 0xc6, 0x12, 0x09, 0x0a,
- // 0x75, 0x30, 0x75, 0x30,
- // 0x00, 0x0c, 0xe6, 0x3b,
- // 0x50, 0x69, 0x6e, 0x67,
- // }
-
- // return outgoing, nil
- return buffer.Bytes(), nil
-}
-
-// func (device *Device) NewICMPv4Packet() []byte {
-// ether := golayers.Ethernet{
-// DstMAC: device.Peer.PeerMAC,
-// SrcMAC: device.LocalMAC,
-// EthernetType: golayers.EthernetTypeIPv4,
-// }
-
-// ip := golayers.IPv4{
-// Version: 4,
-// TOS: 0,
-// Length: 0,
-// Id: 0,
-// FragOffset: 0,
-// TTL: 255,
-// Protocol: golayers.IPProtocolICMPv4,
-// Checksum: 0,
-// SrcIP: device.LocalIPv4,
-// DstIP: device.Peer.PeerIPv4,
-// }
-
-// icmpv4 := golayers.ICMPv4{
-// TypeCode: golayers.CreateICMPv4TypeCode(8, 0),
-// Checksum: 0,
-// Id: 10,
-// Seq: 1,
-// }
-
-// // ICMPv4 Max payload length: 48 byte
-// req_data := []byte{
-// 34, 43, 67, 99,
-// 0, 0, 0, 0,
-// 49, 129, 5, 0,
-// 0, 0, 0, 0,
-// 16, 17, 18, 19,
-// 21, 22, 23, 24,
-// 25, 26, 27, 28,
-// 29, 30, 31, 32,
-// 33, 34, 35, 36,
-// 37, 38, 39, 40,
-// 41, 42, 43, 44,
-// 45, 46, 47, 48,
-// 49, 50, 51, 52,
-// 53, 54, 55, 20,
-// }
-
-// options := gopacket.SerializeOptions{
-// ComputeChecksums: true,
-// FixLengths: true,
-// }
-
-// buffer := gopacket.NewSerializeBuffer()
-
-// if err := gopacket.SerializeLayers(buffer, options,
-// ðer,
-// &ip,
-// &icmpv4,
-// gopacket.Payload(req_data),
-// ); err != nil {
-// logger.LogErr("Serialize error", "error", err)
-// return nil
-// }
-
-// outgoingPacket := buffer.Bytes()
-
-// return outgoingPacket
-// }
diff --git a/client/cmd/main.go b/client/cmd/main.go
index dfd65b8..4074044 100644
--- a/client/cmd/main.go
+++ b/client/cmd/main.go
@@ -1,9 +1,65 @@
package main
import (
- "github.com/GotoRen/echoman/client/exec"
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+
+ "github.com/GotoRen/echoman/client/internal"
+ "github.com/GotoRen/echoman/client/internal/logger"
+ "github.com/joho/godotenv"
)
+func init() {
+ err := godotenv.Load()
+ if err != nil {
+ logger.LogErr("Error loading .env file", "error", err)
+ }
+}
+
func main() {
- exec.Run()
+ logger.InitZap()
+ t := time.NewTicker(time.Second * 1)
+
+ paket_type := os.Getenv("PACKET_TYPE")
+
+ device := internal.GetDeviceInfo(os.Getenv("LOCAL_INTERFACE"))
+ fmt.Println("[INFO] Local Interface Information:", device.IfIndex)
+ fmt.Println("[INFO] Local IPv4 Address:", device.LocalIPv4)
+ fmt.Println("[INFO] Local Hardware Address:", device.LocalMAC)
+ fmt.Println("[INFO] Peer IPv4 Address:", device.Peer.PeerIPv4)
+ fmt.Println("[INFO] Peer Hardware Address:", device.Peer.PeerMAC)
+
+ device.CreateDescriptor()
+ defer syscall.Close(device.Sd4soc)
+ defer syscall.Close(device.Rv4soc)
+
+ device.ListenClient()
+
+ for {
+ <-t.C
+
+ switch paket_type {
+ case "ICMPV4":
+ device.GenerateICMPv4Packet(device.Sd4soc)
+ case "UDPV4":
+ device.GenerateUDPPacket(device.Sd4soc)
+ default:
+ logger.LogErr("You chose a mode that doesn't exist", "error", paket_type)
+ os.Exit(1)
+ }
+
+ buf := make([]byte, 1500)
+ size, _, err := syscall.Recvfrom(device.Rv4soc, buf, 0)
+ if err != nil {
+ fmt.Println("[ERROR] Failed to read packet:", err)
+ }
+ if size < 8 {
+ fmt.Println("error")
+ continue
+ }
+
+ device.RoutineReceiveIncoming(buf, size, device.Sd4soc)
+ }
}
diff --git a/client/debug/dumpfile-client-real.pcapng b/client/debug/dumpfile-client-real.pcapng
deleted file mode 100644
index 377a793..0000000
Binary files a/client/debug/dumpfile-client-real.pcapng and /dev/null differ
diff --git a/client/debug/dumpfile-client-virtual.pcapng b/client/debug/dumpfile-client-virtual.pcapng
deleted file mode 100644
index 19c0e84..0000000
Binary files a/client/debug/dumpfile-client-virtual.pcapng and /dev/null differ
diff --git a/client/debug/dumpfile-client.pcapng b/client/debug/dumpfile-client.pcapng
new file mode 100644
index 0000000..aeff622
Binary files /dev/null and b/client/debug/dumpfile-client.pcapng differ
diff --git a/client/exec/run.go b/client/exec/run.go
deleted file mode 100644
index d35f217..0000000
--- a/client/exec/run.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package exec
-
-import (
- "fmt"
- "os"
- "strconv"
- "time"
-
- "github.com/GotoRen/echoman/client/chorus"
- "github.com/GotoRen/echoman/client/internal"
- "github.com/GotoRen/echoman/client/internal/logger"
- "github.com/joho/godotenv"
-)
-
-func Run() {
- var err error
- t := time.NewTicker(time.Second * 1)
- loadConf()
-
- device := internal.NewDevice(os.Getenv("LOCAL_INTERFACE"))
- fmt.Println("[INFO] IP version:", device.EnvIPver)
- fmt.Println("[INFO] Local IPv4:", device.LocalIPv4)
-
- device.NewPeer()
- fmt.Println("[INFO] Peer IPv4:", device.Peer.PeerEndPoint.IP)
-
- device.CreateTunInterface()
- fmt.Println("[INFO] TUN IPv4:", device.Tun.VIP)
-
- // Create Application
- //=======================================================================//
- device.CreateDescriptor()
- defer device.Close()
-
- device.ChorusPort, err = strconv.Atoi(os.Getenv("CHROUS_PORT"))
- if err != nil {
- fmt.Println(err)
- }
-
- // Listens on ports used by applications (chorus) that use the overlay network.
- chorus.Listen(device.Tun.VIP, device.ChorusPort)
- //=======================================================================//
-
- go device.RoutineSequentialReceiver()
- go device.RoutineSequentialSender()
-
- for {
- <-t.C
- device.NewChorusUDPPacket() // If you want to generate UDP packets, please uncomment here.
- }
-}
-
-func loadConf() {
- err := godotenv.Load()
- if err != nil {
- logger.LogErr("Error loading .env file", "error", err)
- }
-
- logger.InitZap()
-}
diff --git a/client/go.mod b/client/go.mod
index ad194d4..7a6f868 100644
--- a/client/go.mod
+++ b/client/go.mod
@@ -4,18 +4,13 @@ go 1.19
require (
github.com/google/gopacket v1.1.19
- github.com/google/uuid v1.3.0
github.com/joho/godotenv v1.4.0
- github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
- github.com/vishvananda/netlink v1.1.0
go.uber.org/zap v1.23.0
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
- golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
)
require (
- github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
- golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 // indirect
+ golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
)
diff --git a/client/go.sum b/client/go.sum
index a9cd6b2..a2cd1a4 100644
--- a/client/go.sum
+++ b/client/go.sum
@@ -4,22 +4,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
-github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
-github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
-github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
-github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
-github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
@@ -36,11 +28,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g=
-golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/client/chorus/listen.go b/client/internal/client.go
similarity index 60%
rename from client/chorus/listen.go
rename to client/internal/client.go
index b8b9967..d4f6ca6 100644
--- a/client/chorus/listen.go
+++ b/client/internal/client.go
@@ -1,4 +1,4 @@
-package chorus
+package internal
import (
"net"
@@ -6,13 +6,13 @@ import (
"github.com/GotoRen/echoman/client/internal/logger"
)
-func portConf(li string, lp int) (*net.UDPConn, error) {
+func portConf(lp uint16) (*net.UDPConn, error) {
udpAddr := &net.UDPAddr{
- IP: net.ParseIP(li),
- Port: lp,
+ IP: net.IPv4zero.To4(),
+ Port: int(lp),
}
- c, err := net.ListenUDP("udp", udpAddr)
+ c, err := net.ListenUDP("udp4", udpAddr)
if err != nil {
return nil, err
}
@@ -27,8 +27,8 @@ func listenUDPPort(c *net.UDPConn) {
}
}
-func Listen(appIP string, appPort int) {
- conn, err := portConf(appIP, appPort)
+func (device *Device) ListenClient() {
+ conn, err := portConf(device.LocalUDPPort)
if err != nil {
logger.LogErr("Failed to create connection", "error", err)
}
diff --git a/client/internal/conn.go b/client/internal/conn.go
deleted file mode 100644
index 6d10b54..0000000
--- a/client/internal/conn.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package internal
-
-import (
- "net"
- "strconv"
-)
-
-// makeUDPConnection makes UDP Connection.
-func makeUDPConnection(dstPort int) (connUDP *net.UDPConn, err error) {
- udpAddr, err := net.ResolveUDPAddr("udp", ":"+strconv.Itoa(dstPort))
- if err != nil {
- return nil, err
- }
-
- connUDP, err = net.ListenUDP("udp", udpAddr)
- if err != nil {
- return nil, err
- }
-
- return connUDP, nil
-}
-
-// CreateUDPConnection creates a UDP connection with the peer node.
-func CreateUDPConnection(peerUDPport int) (*net.UDPConn, error) {
- connUDP, err := makeUDPConnection(peerUDPport)
- if err != nil {
- return nil, err
- }
-
- return connUDP, nil
-}
diff --git a/client/internal/device.go b/client/internal/device.go
index 6e1cf35..fec2263 100644
--- a/client/internal/device.go
+++ b/client/internal/device.go
@@ -5,109 +5,50 @@ import (
"net"
"os"
"strconv"
- "strings"
"github.com/GotoRen/echoman/client/internal/logger"
)
type Device struct {
- EnvIPver int
-
- // Real Interface
IfIndex *net.Interface
LocalIPv4 net.IP
- LocalIPv6 net.IP
+ LocalMAC net.HardwareAddr
LocalUDPPort uint16
-
- socket struct {
- sd4soc int
- rv4soc int
- }
-
- // TUN/TAP Interface
- Tun struct {
- Device *TunInterface
- VIP string
- mtu int32
- }
-
- ChorusPort int
-
- Peer *Peer
+ Sd4soc int
+ Rv4soc int
+ Peer *Peer
}
-// NewDevice defines device information.
-func NewDevice(intf string) (device *Device) {
- envIPVer, err := strconv.Atoi(os.Getenv("VIRTUAL_IP_TYPE"))
+func GetDeviceInfo(intf string) (device *Device) {
+ interfaces, err := net.Interfaces()
if err != nil {
- logger.LogErr("Unable to get VIRTUAL_IP_TYPE", "error", err)
+ log.Fatal(err)
}
- interfaces, err := net.Interfaces()
+ netInterface, err := net.InterfaceByName(intf)
if err != nil {
log.Fatal(err)
}
localIPv4addr := getServerIPv4(intf, interfaces)
if localIPv4addr == nil {
- logger.LogErr("IPv4 address is empty", "error", err)
- }
-
- device = &Device{
- EnvIPver: envIPVer,
- LocalIPv4: localIPv4addr,
- }
-
- return device
-}
-
-// CreateTunInterface creates a TUN/TAP interface.
-func (device *Device) CreateTunInterface() {
- var err error
-
- vipv4, vipv4prefix := generateVirtualIPv4()
- vipv6, vipv6prefix := generateVirtualIPv6()
-
- switch device.EnvIPver {
- case 4:
- device.Tun.Device, err = NewTunInterface(os.Getenv("TUN_INTERFACE_NAME"), vipv4.String(), vipv4prefix)
- if err != nil {
- logger.LogErr("Unable to create IPv4 TUN/TAP interface", "error", err)
- }
- case 6:
- device.Tun.Device, err = NewTunInterface(os.Getenv("TUN_INTERFACE_NAME"), vipv6.String(), vipv6prefix)
- if err != nil {
- logger.LogErr("Unable to create IPv6 TUN/TAP interface", "error", err)
- }
- }
-
- if err := device.Tun.Device.Up(); err != nil {
- logger.LogErr("Failed to Tunnel up", "error", err)
+ log.Fatal("[ERROR]: ipv4 address is empty.")
}
- device.Tun.VIP = device.Tun.Device.address[:strings.Index(device.Tun.Device.address, "/")]
-}
-
-// CreateDescriptor creates socket descriptor.
-func (device *Device) CreateDescriptor() {
- var err error
+ localMACaddr := netInterface.HardwareAddr
- // send socket
- device.socket.sd4soc, err = SendIPv4RawSocket(device.Tun.VIP)
+ localUDPport, err := strconv.Atoi(os.Getenv("LOCAL_UDP_PORT"))
if err != nil {
- logger.LogErr("Failed to open send IPv4 raw socket", "error", err)
+ logger.LogErr("Type conversion failed", "error", err)
}
- // receive socket
- device.socket.rv4soc, err = RecvIPv4RawSocket(device.Tun.VIP)
- if err != nil {
- logger.LogErr("Failed to open receive IPv4 raw socket", "error", err)
+ device = &Device{
+ IfIndex: netInterface,
+ LocalIPv4: localIPv4addr,
+ LocalMAC: localMACaddr,
+ LocalUDPPort: uint16(localUDPport),
+ Peer: GerPeerInfo(),
}
-}
-// Close closes device's queue, workers.
-func (device *Device) Close() {
- closeRawSocket(device.socket.sd4soc, "send IPv4")
- closeRawSocket(device.socket.rv4soc, "receive IPv4")
- logger.LogDebug("Device closed")
+ return device
}
diff --git a/client/internal/handle_icmpv4.go b/client/internal/handle_icmpv4.go
new file mode 100644
index 0000000..a3e29c9
--- /dev/null
+++ b/client/internal/handle_icmpv4.go
@@ -0,0 +1,74 @@
+package internal
+
+import (
+ "github.com/GotoRen/echoman/client/internal/logger"
+ "github.com/google/gopacket"
+ golayers "github.com/google/gopacket/layers"
+)
+
+func (device *Device) NewICMPv4Packet() []byte {
+ ether := golayers.Ethernet{
+ DstMAC: device.Peer.PeerMAC,
+ SrcMAC: device.LocalMAC,
+ EthernetType: golayers.EthernetTypeIPv4,
+ }
+
+ ip := golayers.IPv4{
+ Version: 4,
+ TOS: 0,
+ Length: 0,
+ Id: 0,
+ FragOffset: 0,
+ TTL: 255,
+ Protocol: golayers.IPProtocolICMPv4,
+ Checksum: 0,
+ SrcIP: device.LocalIPv4,
+ DstIP: device.Peer.PeerIPv4,
+ }
+
+ icmpv4 := golayers.ICMPv4{
+ TypeCode: golayers.CreateICMPv4TypeCode(8, 0),
+ Checksum: 0,
+ Id: 10,
+ Seq: 1,
+ }
+
+ // ICMPv4 Max payload length: 48 byte
+ req_data := []byte{
+ 34, 43, 67, 99,
+ 0, 0, 0, 0,
+ 49, 129, 5, 0,
+ 0, 0, 0, 0,
+ 16, 17, 18, 19,
+ 21, 22, 23, 24,
+ 25, 26, 27, 28,
+ 29, 30, 31, 32,
+ 33, 34, 35, 36,
+ 37, 38, 39, 40,
+ 41, 42, 43, 44,
+ 45, 46, 47, 48,
+ 49, 50, 51, 52,
+ 53, 54, 55, 20,
+ }
+
+ options := gopacket.SerializeOptions{
+ ComputeChecksums: true,
+ FixLengths: true,
+ }
+
+ buffer := gopacket.NewSerializeBuffer()
+
+ if err := gopacket.SerializeLayers(buffer, options,
+ ðer,
+ &ip,
+ &icmpv4,
+ gopacket.Payload(req_data),
+ ); err != nil {
+ logger.LogErr("Serialize error", "error", err)
+ return nil
+ }
+
+ outgoingPacket := buffer.Bytes()
+
+ return outgoingPacket
+}
diff --git a/client/internal/handle_udp.go b/client/internal/handle_udp.go
new file mode 100644
index 0000000..e42a82b
--- /dev/null
+++ b/client/internal/handle_udp.go
@@ -0,0 +1,61 @@
+package internal
+
+import (
+ "github.com/GotoRen/echoman/client/internal/logger"
+ "github.com/google/gopacket"
+ golayers "github.com/google/gopacket/layers"
+)
+
+func (device *Device) NewUDPPacket() []byte {
+ ether := golayers.Ethernet{
+ DstMAC: device.Peer.PeerMAC,
+ SrcMAC: device.LocalMAC,
+ EthernetType: golayers.EthernetTypeIPv4,
+ }
+
+ ip := golayers.IPv4{
+ Version: 4,
+ TOS: 0,
+ Length: 0,
+ Id: 0,
+ FragOffset: 0,
+ TTL: 255,
+ Protocol: golayers.IPProtocolUDP,
+ Checksum: 0,
+ SrcIP: device.LocalIPv4,
+ DstIP: device.Peer.PeerIPv4,
+ }
+
+ udp := golayers.UDP{
+ SrcPort: golayers.UDPPort(device.LocalUDPPort),
+ DstPort: golayers.UDPPort(device.Peer.PeerUDPPort),
+ }
+ data := []byte("Ping")
+
+ // calculating checksum
+ if err := udp.SetNetworkLayerForChecksum(&ip); err != nil {
+ logger.LogErr("udp set error", "error", err)
+ return nil
+ }
+
+ options := gopacket.SerializeOptions{
+ ComputeChecksums: true,
+ FixLengths: true,
+ }
+
+ buffer := gopacket.NewSerializeBuffer()
+
+ if err := gopacket.SerializeLayers(buffer, options,
+ ðer,
+ &ip,
+ &udp,
+ gopacket.Payload(data),
+ ); err != nil {
+ logger.LogErr("Serialize error", "error", err)
+ return nil
+ }
+
+ outgoingPacket := buffer.Bytes()
+
+ return outgoingPacket
+}
diff --git a/client/internal/handler.go b/client/internal/handler.go
new file mode 100644
index 0000000..17875d0
--- /dev/null
+++ b/client/internal/handler.go
@@ -0,0 +1,29 @@
+package internal
+
+import (
+ "fmt"
+ "log"
+
+ "github.com/GotoRen/echoman/client/layers"
+)
+
+func (device *Device) GenerateICMPv4Packet(fd int) {
+ icmpv4Packet := device.NewICMPv4Packet()
+ // layers.UnmarshalIPv4Packet(icmpv4Packet)
+ // layers.UnmarshalICMPv4Packet(icmpv4Packet)
+ if err := SendEtherPacket(fd, icmpv4Packet); err != nil {
+ log.Fatal(err)
+ } else {
+ fmt.Println("[INFO] Received ICMPv4 echo request")
+ }
+}
+
+func (device *Device) GenerateUDPPacket(fd int) {
+ udpPacket := device.NewUDPPacket()
+ // layers.UnmarshalIPv4Packet(udpPacket)
+ // layers.UnmarshalICMPv4Packet(udpPacket)
+ layers.DebugUDPMessage(udpPacket)
+ if err := SendEtherPacket(fd, udpPacket); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/client/internal/peer.go b/client/internal/peer.go
index be4ab34..57d0431 100644
--- a/client/internal/peer.go
+++ b/client/internal/peer.go
@@ -9,32 +9,29 @@ import (
)
type Peer struct {
- // Network information
- PeerEndPoint net.UDPAddr
-
- // UDP connection
- ConnUDP *net.UDPConn
+ PeerIPv4 net.IP
+ PeerMAC net.HardwareAddr
+ PeerUDPPort uint16
}
-// NewPeer creates peer network information and UDP connections.
-func (device *Device) NewPeer() {
+func GerPeerInfo() (peer *Peer) {
peerIPv4addr := net.ParseIP(os.Getenv("PEER_IPV4_ADDRESS"))
- peerUDPport, err := strconv.Atoi(os.Getenv("PEER_UDP_PORT"))
+ peerMACaddr, err := net.ParseMAC(os.Getenv("PEER_MAC_ADDRESS"))
if err != nil {
- logger.LogErr("Type conversion failed", "error", err)
+ logger.LogErr("MAC address parse error", "error", err)
}
- connUDP, err := CreateUDPConnection(peerUDPport)
+ peerUDPport, err := strconv.Atoi(os.Getenv("PEER_UDP_PORT"))
if err != nil {
- logger.LogErr("Unable to establish UDP connection", "error", err)
+ logger.LogErr("Type conversion failed", "error", err)
}
- device.Peer = &Peer{
- PeerEndPoint: net.UDPAddr{
- IP: peerIPv4addr,
- Port: peerUDPport,
- },
- ConnUDP: connUDP,
+ peer = &Peer{
+ PeerIPv4: peerIPv4addr,
+ PeerMAC: peerMACaddr,
+ PeerUDPPort: uint16(peerUDPport),
}
+
+ return peer
}
diff --git a/client/internal/raw_socket.go b/client/internal/raw_socket.go
index e44bcec..f99cb46 100644
--- a/client/internal/raw_socket.go
+++ b/client/internal/raw_socket.go
@@ -1,6 +1,7 @@
package internal
import (
+ "log"
"net"
"syscall"
@@ -11,10 +12,6 @@ func htons(host uint16) uint16 {
return (host&0xff)<<8 | (host >> 8)
}
-// ========================================================================= //
-// L2 socket
-// ========================================================================= //
-
// etherSendSock creates a new send socket for IPv4 ethernet packet.
func etherSendSock(intfIndex *net.Interface) (int, error) {
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_IP)))
@@ -57,7 +54,7 @@ func etherRecvSock(intfIndex *net.Interface) (int, error) {
return fd, nil
}
-// SendEtherPacket uses a send socket to send an ether packet.
+// SendEtherPacket uses a send socket to send an Ethernete packet.
func SendEtherPacket(fd int, b []byte) error {
if _, err := syscall.Write(fd, b); err != nil {
return err
@@ -66,82 +63,19 @@ func SendEtherPacket(fd int, b []byte) error {
return nil
}
-// RecvEtherPacket uses a receive socket to receive an ether packet.
-func RecvEtherPacket(fd int, b []byte) error {
- if _, err := syscall.Read(fd, b); err != nil {
- return err
- }
-
- return nil
-}
-
-// ========================================================================= //
-// L3 socket
-// ========================================================================= //
+// CreateDescriptor creates socket descriptor.
+func (device *Device) CreateDescriptor() {
+ var err error
-// SendIPv4RawSocket creates a raw socket for sending IPv4 packet.
-func SendIPv4RawSocket(dip string) (int, error) {
- fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
+ // send socket
+ device.Sd4soc, err = etherSendSock(device.IfIndex)
if err != nil {
- return -1, err
- }
-
- ip := net.ParseIP(dip)
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
+ logger.LogErr("Failed to open send IPv4 raw socket", "error", err)
}
- if err = syscall.Bind(fd, &addr); err != nil {
- return -1, err
- }
-
- return fd, nil
-}
-
-// RecvIPv4RawSocket creates a raw socket for receiving IPv4 packet.
-func RecvIPv4RawSocket(sip string) (int, error) {
- fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
+ // receive socket
+ device.Rv4soc, err = etherRecvSock(device.IfIndex)
if err != nil {
- return -1, err
- }
-
- ip := net.ParseIP(sip)
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
- }
-
- if err = syscall.Bind(fd, &addr); err != nil {
- return -1, err
- }
-
- return fd, nil
-}
-
-// SendPacket4 sends IPv4 packet.
-func SendPacket4(fd int, b []byte, dip []byte) error {
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{dip[0], dip[1], dip[2], dip[3]},
- }
-
- if err := syscall.Sendto(fd, b, 0, &addr); err != nil {
- return err
- }
-
- return nil
-}
-
-// ========================================================================= //
-// Socket controller
-// ========================================================================= //
-
-// closeRawSocket closes opening file descriptor.
-func closeRawSocket(fd int, fdType string) {
- if fd == -1 {
- return
- }
-
- if err := syscall.Close(fd); err != nil {
- message := "Failed to close the " + fdType + " Raw socket"
- logger.LogErr(message, "error", err)
+ log.Fatal(err)
}
}
diff --git a/client/internal/read_packet.go b/client/internal/read_packet.go
index 7599deb..b024ce1 100644
--- a/client/internal/read_packet.go
+++ b/client/internal/read_packet.go
@@ -1,86 +1,111 @@
package internal
import (
+ "encoding/binary"
"fmt"
- "os"
"github.com/GotoRen/echoman/client/internal/logger"
+ "github.com/GotoRen/echoman/client/layers"
"github.com/google/gopacket"
golayers "github.com/google/gopacket/layers"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
)
-func (device *Device) ReadIPv4Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+func (device *Device) RoutineReceiveIncoming(buf []byte, size, sd4soc int) {
+ packet := gopacket.NewPacket(buf[:size], golayers.LayerTypeEthernet, gopacket.Default)
+ eh := &layers.EtherHeader{
+ DstMacAddr: buf[layers.DstMACAddrOffset : layers.DstMACAddrOffset+layers.DstMacLength],
+ SrcMacAddr: buf[layers.SrcMACAddrOffset : layers.SrcMACAddrOffset+layers.SrcMacLength],
+ ProtoType: binary.BigEndian.Uint16(buf[layers.Protocoloffset : layers.Protocoloffset+layers.ProtocolTypeLength]),
+ }
- icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
- if icmpv4Layer != nil {
- icmpv4 := icmpv4Layer.(*golayers.ICMPv4)
- switch icmpv4.TypeCode.Type() {
- case golayers.ICMPv4TypeEchoRequest:
- fmt.Println("[DEBUG] Received ICMPv4 echo request")
- case golayers.ICMPv4TypeEchoReply:
- fmt.Println("[DEBUG] Received ICMPv4 echo replay")
- default:
- logger.LogErr("Unknown ICMPv4 packet type", "error", icmpv4.TypeCode.Type())
- os.Exit(1)
+ switch eh.ProtoType {
+ case layers.EthTypeIpv4:
+ if len(buf[layers.Etherlen:size]) < ipv4.HeaderLen {
+ logger.LogErr("Received IPv4 packet is too small", "error", len(buf[layers.Etherlen:size]))
}
- }
- udpLayer := packet.Layer(golayers.LayerTypeUDP)
- if udpLayer != nil {
- udp := udpLayer.(*golayers.UDP)
- switch udp.DstPort.LayerType() {
- case golayers.LayerTypeDHCPv4:
- fmt.Println("[DEBUG] Received DHCPv4 packet")
- case golayers.LayerTypeDNS:
- fmt.Println(("[DEBUG] Received DNS A record packet"))
- default:
- logger.LogErr("Unknown IPv4 UDP packet type", "error", udp.DstPort.LayerType())
- os.Exit(1)
+ icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
+ if icmpv4Layer != nil {
+ icmpv4 := icmpv4Layer.(*golayers.ICMPv4)
+ switch icmpv4.TypeCode.Type() {
+ case golayers.ICMPv4TypeDestinationUnreachable:
+ fmt.Println("[ERROR] Received ICMPv4 Destination Unreachable")
+ case golayers.ICMPv4TypeEchoRequest:
+ // Do nothing.
+ case golayers.ICMPv4TypeEchoReply:
+ fmt.Println("[INFO] Received ICMPv4 echo replay")
+ default:
+ logger.LogErr("Unknown ICMPv4 packet type", "error", icmpv4.TypeCode.Type())
+ }
}
- }
-}
-func (device *Device) ReadIPv6Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv6, gopacket.Default)
+ udpLayer := packet.Layer(golayers.LayerTypeUDP)
+ if udpLayer != nil {
+ udp := udpLayer.(*golayers.UDP)
+ switch udp.DstPort.LayerType() {
+ case golayers.LayerTypeDHCPv4:
+ logger.LogDebug("Received DHCPv4 packet", "DHCPv4", udp.DstPort.LayerType())
+ case golayers.LayerTypeDNS:
+ logger.LogDebug("Received DNS A record packet", "DNS", udp.DstPort.LayerType())
+ default:
+ if udp.DstPort == golayers.UDPPort(device.Peer.PeerUDPPort) {
+ // Echoman requst
+ // Do nothing.
+ } else if udp.DstPort == golayers.UDPPort(device.LocalUDPPort) {
+ // Echoman response
+ layers.DebugUDPMessage(buf)
+ } else {
+ logger.LogErr("Unknown IPv4 UDP packet type", "error", udp.DstPort)
+ }
+ }
+ }
+ case layers.EthTypeIpv6:
+ if len(buf[layers.Etherlen:size]) < ipv6.HeaderLen {
+ logger.LogErr("Received IPv6 packet is too small", "error", len(buf[layers.Etherlen:size]))
+ }
- icmpv6Layer := packet.Layer(golayers.LayerTypeICMPv6)
- if icmpv6Layer != nil {
- icmpv6 := icmpv6Layer.(*golayers.ICMPv6)
- switch icmpv6.TypeCode.Type() {
- case golayers.ICMPv6TypeDestinationUnreachable:
- fmt.Println("[DEBUG] Received ICMPv6 Destination Unreachable")
- case golayers.ICMPv6TypeEchoRequest:
- fmt.Println("[DEBUG] Received ICMPv6 echo request")
- case golayers.ICMPv6TypeEchoReply:
- fmt.Println("[DEBUG] Received ICMPv6 echo replay")
- case golayers.ICMPv6TypeRouterSolicitation:
- fmt.Println("[DEBUG] Received Router Solicitation")
- case golayers.ICMPv6TypeRouterAdvertisement:
- fmt.Println("[DEBUG] Received Router Advertisement")
- case golayers.ICMPv6TypeNeighborSolicitation:
- fmt.Println("[DEBUG] Received Neighbor Solicitation")
- case golayers.ICMPv6TypeNeighborAdvertisement:
- fmt.Println("[DEBUG] Received Neighbor Advertisement")
- case golayers.ICMPv6TypeMLDv2MulticastListenerReportMessageV2:
- fmt.Println("[DEBUG] Received Multicast ListenerReport MessageV2")
- default:
- logger.LogErr("Unknown ICMPv6 packet type", "error", icmpv6.TypeCode.Type())
- os.Exit(1)
+ icmpv6Layer := packet.Layer(golayers.LayerTypeICMPv6)
+ if icmpv6Layer != nil {
+ icmpv6 := icmpv6Layer.(*golayers.ICMPv6)
+ switch icmpv6.TypeCode.Type() {
+ case golayers.ICMPv6TypeDestinationUnreachable:
+ fmt.Println("[ERROR] Received ICMPv6 Destination Unreachable")
+ case golayers.ICMPv6TypeEchoRequest:
+ logger.LogDebug("Received ICMPv6 echo request", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeEchoReply:
+ logger.LogDebug("Received ICMPv6 echo replay", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeRouterSolicitation:
+ logger.LogDebug("Received Router Solicitation", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeRouterAdvertisement:
+ logger.LogDebug("Received Router Advertisement", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeNeighborSolicitation:
+ logger.LogDebug("Received Neighbor Solicitation", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeNeighborAdvertisement:
+ logger.LogDebug("Received Neighbor Advertisement", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeMLDv2MulticastListenerReportMessageV2:
+ logger.LogDebug("Received Multicast ListenerReport MessageV2", "ICMPv6", icmpv6.TypeCode.Type())
+ default:
+ logger.LogErr("Unknown ICMPv6 packet type", "error", icmpv6.TypeCode.Type())
+ }
}
- }
- udpLayer := packet.Layer(golayers.LayerTypeUDP)
- if udpLayer != nil {
- udp := udpLayer.(*golayers.UDP)
- switch udp.DstPort.LayerType() {
- case golayers.LayerTypeDHCPv6:
- fmt.Println(("[DEBUG] Received DHCPv6 packet"))
- case golayers.LayerTypeDNS:
- fmt.Println(("[DEBUG] Received DNS AAAA record packet"))
- default:
- logger.LogErr("Unknown IPv6 UDP packet type", "error", udp.DstPort.LayerType())
- os.Exit(1)
+ udpLayer := packet.Layer(golayers.LayerTypeUDP)
+ if udpLayer != nil {
+ udp := udpLayer.(*golayers.UDP)
+ switch udp.DstPort.LayerType() {
+ case golayers.LayerTypeDHCPv6:
+ logger.LogDebug("Received DHCPv6 packet", "DHCPv6", udp.DstPort.LayerType())
+ case golayers.LayerTypeDNS:
+ logger.LogDebug("Received DNS AAAA record packet", "DNS", udp.DstPort.LayerType())
+ default:
+ logger.LogErr("Unknown IPv6 UDP packet type", "error", udp.DstPort.LayerType())
+ }
}
+ case layers.EthTypeArp:
+ fmt.Println("[INFO] Received ARP packet")
+ default:
+ logger.LogErr("Detect unknown protocol version", "error", eh.ProtoType)
}
}
diff --git a/client/internal/receive.go b/client/internal/receive.go
deleted file mode 100644
index 18143d1..0000000
--- a/client/internal/receive.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package internal
-
-import (
- "fmt"
-
- "github.com/GotoRen/echoman/client/internal/logger"
- "github.com/GotoRen/echoman/client/layers"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-// RoutineSequentialReceiver forwards the peer's packets obtained from
-// the real interface to the virtual interface.
-func (device *Device) RoutineSequentialReceiver() {
- for {
- buf := make([]byte, 1500)
- size, _, err := device.Peer.ConnUDP.ReadFrom(buf)
- if err != nil {
- logger.LogErr("Failed to receive UDP packet", "error", err)
- }
-
- if size == 0 {
- logger.LogErr("Received packet is too small", "error", size)
- continue
- }
-
- switch buf[0] >> 4 {
- case ipv4.Version:
- if len(buf) < ipv4.HeaderLen {
- logger.LogErr("Received IPv4 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // dst := buf[layers.IPv4offsetDst : layers.IPv4offsetDst+net.IPv4len]
- // fmt.Println("[INFO] Peer IPv4 Address", dst)
-
- layers.DebugUDPMessage(buf) // Receive debug
-
- if _, err := device.Tun.Device.Tun.Write(buf); err != nil {
- logger.LogErr("Failed to write to tun/tap interface", "error", err)
- }
-
- case ipv6.Version:
- if len(buf) < ipv6.HeaderLen {
- logger.LogErr("Received IPv6 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // dst := buf[layers.IPv6offsetDst : layers.IPv6offsetDst+net.IPv6len]
- // fmt.Println("[INFO] Peer IPv6 Address", dst)
-
- if _, err := device.Tun.Device.Tun.Write(buf); err != nil {
- logger.LogErr("Failed to write to tun/tap interface", "error", err)
- }
-
- default:
- fmt.Println("ip version error")
- }
- }
-}
diff --git a/client/internal/send.go b/client/internal/send.go
deleted file mode 100644
index 6d89d5e..0000000
--- a/client/internal/send.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package internal
-
-import (
- "net"
- "os"
-
- "github.com/GotoRen/echoman/client/chorus"
- "github.com/GotoRen/echoman/client/internal/logger"
- "github.com/GotoRen/echoman/client/layers"
- golayers "github.com/google/gopacket/layers"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-// RoutineSequentialSender sends packets obtained from a virtual interface to the peer.
-func (device *Device) RoutineSequentialSender() {
- for {
- buf := make([]byte, 1500)
- size, err := device.Tun.Device.Read(buf)
- if err != nil {
- logger.LogErr("Failed to receive virtual IP packet", "error", err)
- }
-
- if size == 0 {
- logger.LogErr("Received packet is too small", "error", size)
- continue
- }
-
- switch buf[0] >> 4 {
- case ipv4.Version:
- if len(buf) < ipv4.HeaderLen {
- logger.LogErr("Received IPv4 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // fmt.Println("[DEBUG] Received IPv4 packet from TUN/TAP", buf[:size])
- // dst := buf[layers.IPv4offsetDst : layers.IPv4offsetDst+net.IPv4len]
-
- layers.DebugUDPMessage(buf) // Send debug
-
- if _, err := device.Peer.ConnUDP.WriteToUDP(buf, &device.Peer.PeerEndPoint); err != nil {
- logger.LogErr("Failed to write to real interface", "error", err)
- }
-
- case ipv6.Version:
- if len(buf) < ipv6.HeaderLen {
- logger.LogErr("Received IPv6 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // fmt.Println("[DEBUG] Received IPv6 packet from TUN/TAP", buf[:size])
- // dst := buf[layers.IPv6offsetDst : layers.IPv6offsetDst+net.IPv6len]
-
- if _, err := device.Peer.ConnUDP.WriteToUDP(buf, &device.Peer.PeerEndPoint); err != nil {
- logger.LogErr("Failed to write virtual IPv6 Packet", "error", err)
- }
-
- default:
- logger.LogErr("ip version error", "error", buf[0]>>4)
- }
- }
-}
-
-// NewChorusUDPPacket sends the generated UDP packet.
-func (device *Device) NewChorusUDPPacket() {
- srcVIPv4 := net.ParseIP(device.Tun.VIP).To4()
- dstVIPv4 := net.ParseIP(os.Getenv("ECHOMAN_SERVER_IPV4_TUN")).To4()
- chorusPort := golayers.UDPPort(device.ChorusPort)
-
- udpPacket, err := chorus.GenerateUDPRequestPacket(srcVIPv4, dstVIPv4, chorusPort)
- if err != nil {
- logger.LogErr("Failed to generate udp packet", "error", err)
- }
-
- // write to the tun/tap interface
- if err := SendPacket4(device.socket.sd4soc, udpPacket, dstVIPv4); err != nil {
- logger.LogErr("Failed to write to tun/tap interface", "error", err)
- }
-}
diff --git a/client/internal/tun.go b/client/internal/tun.go
deleted file mode 100644
index 797225e..0000000
--- a/client/internal/tun.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Package internal contains the TCP/UDP connection,
-// setups TUN/TAP Device, handles DNS packets.
-package internal
-
-import (
- "fmt"
- "os/exec"
- "runtime"
-
- "github.com/GotoRen/echoman/client/internal/logger"
- "github.com/songgao/water"
- "github.com/vishvananda/netlink"
- "golang.org/x/xerrors"
-)
-
-// TunInterface manages Tunnel device.
-type TunInterface struct {
- Tun *water.Interface
- address string
-}
-
-// NewTunInterface returns Tunnel device.
-func NewTunInterface(name string, address string, prefix string) (*TunInterface, error) {
- addr := address + prefix
-
- switch runtime.GOOS {
- case "linux":
- config := water.Config{
- DeviceType: water.TUN,
- }
- config.Name = name
-
- ifce, err := water.New(config)
- if err != nil {
- return nil, err
- }
-
- iface := &TunInterface{
- Tun: ifce,
- address: addr,
- }
-
- return iface, nil
-
- case "darwin":
- ifce, err := water.New(water.Config{
- DeviceType: water.TUN,
- })
- if err != nil {
- return nil, err
- }
-
- iface := &TunInterface{
- Tun: ifce,
- address: addr,
- }
-
- return iface, nil
-
- case "windows":
- return nil, xerrors.Errorf("Windows is not supported")
- default:
- return nil, xerrors.Errorf("%s is not supported", runtime.GOOS)
- }
-}
-
-// Up function ups a virtual interface.
-func (iface *TunInterface) Up() error {
- switch runtime.GOOS {
- case "linux":
- out, err := execCmd("ip", []string{"addr", "add", iface.address, "dev", iface.Tun.Name()})
- logger.LogDebug("Add a Virtual Interface", "Virtual Interface", out)
-
- if err != nil {
- logger.LogErr("ip command add fail", "error", err)
- return err
- }
-
- set, err := execCmd("ip", []string{"link", "set", "dev", iface.Tun.Name(), "up", "mtu", "1460"})
- logger.LogDebug("Up a Virtual Interface", "Virtual Interface", set)
-
- if err != nil {
- logger.LogErr("ip command set fail", "error", err)
- return err
- }
-
- case "darwin":
- out, err := execCmd("ifconfig", []string{iface.Tun.Name(), "up"})
- logger.LogDebug("Add a Virtual Interface", "Virtual Interface", out)
-
- if err != nil {
- logger.LogErr("ifconfig fail", "error", err)
- return err
- }
-
- if tun, err := netlink.LinkByName(iface.Tun.Name()); err == nil {
- addr, err := netlink.ParseAddr(iface.address)
- if err != nil {
- logger.LogErr("Unable to parse address", "error", err)
- }
-
- if err := netlink.AddrAdd(tun, addr); err != nil {
- logger.LogErr("Unable to add IP address to linked device", "error", err)
- }
-
- // TODO: Change MTU
-
- logger.LogDebug("Check Virtual Interface Name", "Virtual Interface Name", iface.Tun.Name())
- logger.LogDebug("Check Virtual Interface Address", "Virtual Interface Address", iface.address)
- }
-
- default:
- logger.LogErr("unsupported", "error", runtime.GOOS)
- logger.LogErr("unsupported", "error", runtime.GOARCH)
- return fmt.Errorf("unsupported: %s %s", runtime.GOOS, runtime.GOARCH)
- }
-
- return nil
-}
-
-// Read function read the virtual interface.
-func (iface *TunInterface) Read(buf []byte) (int, error) {
- n, err := iface.Tun.Read(buf)
- // Read Virtual Interface.
- if err != nil {
- logger.LogErr("Failed to read virtual interface", "error", err)
- return 0, err
- }
-
- return n, nil
-}
-
-// Write function write the virtual interface.
-func (iface *TunInterface) Write(buf []byte) (int, error) {
- return iface.Tun.Write(buf)
-}
-
-// Close function closes the virtual interface.
-func (iface *TunInterface) Close() {
- if err := iface.Tun.Close(); err != nil {
- logger.LogErr("Failed to close virtual interface", "error", err)
- }
-}
-
-// execCmd executes the given arguments as a command.
-func execCmd(cmd string, args []string) (string, error) {
- execCmd := exec.Command(cmd, args...)
- if err := execCmd.Run(); err != nil {
- logger.LogErr("Unable to execute command ", "error", err.Error())
- return execCmd.String(), err
- }
-
- return execCmd.String(), nil
-}
diff --git a/client/internal/vip.go b/client/internal/vip.go
deleted file mode 100644
index 02dcd28..0000000
--- a/client/internal/vip.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package internal
-
-import (
- "crypto/rand"
- "encoding/binary"
- "fmt"
- "net"
- "strings"
-
- "github.com/GotoRen/echoman/client/internal/logger"
- "github.com/google/uuid"
-)
-
-// rfc3330, rfc2544.
-// Using the Documentation addresses and prefixes.
-var VIPv4NetworkAddress string = "198.18.0.0/16"
-var VIPv6NetworkAddress string = "2001:0db8:c0ff:ee00::/64"
-
-// getVIPv4NetworkAddressInfo returns information about virtual IPv4 overlay network.
-func getVIPv4NetworkAddressInfo() (vipv4nwaddress net.IP, vipv4netmask net.IPMask, vipv4prefix string) {
- _, ipnet, err := net.ParseCIDR(VIPv4NetworkAddress)
- if err != nil {
- logger.LogErr("Unable to get Virtual IPv4 network address", "error", err)
- }
-
- vipv4nwaddress = ipnet.IP
- vipv4netmask = ipnet.Mask
- vipv4prefix = VIPv4NetworkAddress[strings.Index(VIPv4NetworkAddress, "/"):]
-
- return
-}
-
-// getVIPv6NetworkAddressInfo returns information about virtual IPv6 overlay network.
-func getVIPv6NetworkAddressInfo() (vipv6nwaddress net.IP, vipv6netmask net.IPMask, vipv6prefix string) {
- _, ipnet, err := net.ParseCIDR(VIPv6NetworkAddress)
- if err != nil {
- logger.LogErr("Unable to get Virtual IPv4 network address", "error", err)
- }
-
- vipv6nwaddress = ipnet.IP
- vipv6netmask = ipnet.Mask
- vipv6prefix = VIPv6NetworkAddress[strings.Index(VIPv6NetworkAddress, "/"):]
-
- return
-}
-
-// generateVirtualIPv4 is to generate virtual IPv4 address.
-func generateVirtualIPv4() (net.IP, string) {
- vipv4nwaddress, _, vipv4prefix := getVIPv4NetworkAddressInfo()
- b := make([]byte, 2)
-
-createVIPv4:
- err := binary.Read(rand.Reader, binary.BigEndian, &b)
- if err != nil {
- logger.LogErr("Failed to generate random 2 bytes for VirtualIPv4", "error", err)
- }
-
- vipv4 := net.IPv4(vipv4nwaddress[0], vipv4nwaddress[1], b[0], b[1]).To4()
-
- // TODO: If you use netip.Addr type you can use switch-case.
- // 198.18.0.0/16 => network address or 198.18.255.255/16 => broadcast address
- if vipv4.Equal(net.IPv4(vipv4nwaddress[0], vipv4nwaddress[1], 0x00, 0x00).To4()) || vipv4.Equal(net.IPv4(vipv4nwaddress[0], vipv4nwaddress[1], 0xff, 0xff).To4()) {
- goto createVIPv4
- }
-
- return vipv4, vipv4prefix
-}
-
-// generateVirtualIPv6 is to generate virtual IPv6 address.
-func generateVirtualIPv6() (net.IP, string) {
- vipv6nwaddress, _, vipv6prefix := getVIPv6NetworkAddressInfo()
-
- u, err := uuid.NewRandom()
- if err != nil {
- logger.LogErr("Failed to generate UUID for VirtualIPv6", "error", err)
- }
-
- ub, err := u.MarshalBinary()
- if err != nil {
- logger.LogErr("For VirtualIPv6: Failed encode to binary format", "error", err)
- }
-
- vipv6 := net.ParseIP(strings.Replace(vipv6nwaddress.String(), "::", fmt.Sprintf(":%x:%x:%x:%x", ub[8:10], ub[10:12], ub[12:14], ub[14:16]), 1))
-
- return vipv6, vipv6prefix
-}
diff --git a/client/layers/icmpv4.go b/client/layers/icmpv4.go
index 092a20f..c0f450e 100644
--- a/client/layers/icmpv4.go
+++ b/client/layers/icmpv4.go
@@ -39,7 +39,7 @@ const (
)
func UnmarshalICMPv4Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
if icmpv4Layer != nil {
icmpv4, _ := icmpv4Layer.(*golayers.ICMPv4)
@@ -54,7 +54,7 @@ func UnmarshalICMPv4Packet(b []byte) {
}
func DebugICMPv4Message(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
if icmpv4Layer != nil {
icmpv4, _ := icmpv4Layer.(*golayers.ICMPv4)
diff --git a/client/layers/ipv4.go b/client/layers/ipv4.go
index f85ed4a..c77147b 100644
--- a/client/layers/ipv4.go
+++ b/client/layers/ipv4.go
@@ -2,7 +2,6 @@ package layers
import (
"fmt"
- "net"
"github.com/google/gopacket"
golayers "github.com/google/gopacket/layers"
@@ -41,15 +40,13 @@ const (
DstIPv4Length = 4
)
-// IPv4 offset length.
const (
- IPv4offsetTotalLength = 2 // IPv4offsetPayloadLength is IPv4 offset payload length.
- IPv4offsetSrc = 12 // IPv4offsetSrc is IPv4 offset src length.
- IPv4offsetDst = IPv4offsetSrc + net.IPv4len // IPv4offsetDst is IPv4 offset dst length.
+ SrcIPv4AddrOffset = 26
+ DstIPv4AddrOffset = 30
)
func UnmarshalIPv4Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
ipv4Layer := packet.Layer(golayers.LayerTypeIPv4)
if ipv4Layer != nil {
ipv4, _ := ipv4Layer.(*golayers.IPv4)
diff --git a/client/layers/ipv6.go b/client/layers/ipv6.go
deleted file mode 100644
index eab3021..0000000
--- a/client/layers/ipv6.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package layers
-
-import "net"
-
-// IPv6 offset length.
-const (
- IPv6offsetPayloadLength = 4 // IPv6offsetPayloadLength is IPv6 offset payload length.
- IPv6offsetSrc = 8 // IPv6offsetSrc is IPv6 offset src length.
- IPv6offsetDst = IPv6offsetSrc + net.IPv6len // IPv6offsetDst is IPv6 offset dst length.
-)
diff --git a/client/layers/udp.go b/client/layers/udp.go
index ace08bf..bb68f73 100644
--- a/client/layers/udp.go
+++ b/client/layers/udp.go
@@ -13,12 +13,12 @@ const (
)
const (
- SrcUDPPortOffset = 20
- DstUDPPortOffset = 22
+ SrcUDPPortOffset = 34
+ DstUDPPortOffset = 36
)
func UnmarshalUDPPacket(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
udpLayer := packet.Layer(golayers.LayerTypeUDP)
if udpLayer != nil {
udp, _ := udpLayer.(*golayers.UDP)
@@ -34,7 +34,7 @@ func UnmarshalUDPPacket(b []byte) {
}
func DebugUDPMessage(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
udpLayer := packet.Layer(golayers.LayerTypeUDP)
if udpLayer != nil {
udp, _ := udpLayer.(*golayers.UDP)
diff --git a/compose.yaml b/compose.yaml
index e645072..f845115 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -9,11 +9,10 @@ services:
networks:
echoman:
ipv4_address: 10.0.3.95
- ipv6_address: fde4:db8::0395
privileged: true
restart: always
sysctls:
- net.ipv6.conf.all.disable_ipv6: "0" # enable
+ net.ipv6.conf.all.disable_ipv6: "1"
tty: true
volumes:
- type: bind
@@ -31,11 +30,10 @@ services:
networks:
echoman:
ipv4_address: 10.0.3.96
- ipv6_address: fde4:db8::0396
privileged: true
restart: always
sysctls:
- net.ipv6.conf.all.disable_ipv6: "0" # enable
+ net.ipv6.conf.all.disable_ipv6: "1"
tty: true
volumes:
- type: bind
@@ -51,6 +49,5 @@ networks:
driver: bridge
ipam:
config:
- - subnet: 10.0.3.0/22
- - subnet: fde4:db8::/8
- enable_ipv6: true
+ - subnet: 10.0.3.0/24
+ enable_ipv6: false
diff --git a/docs/01_information.md b/docs/01_information.md
deleted file mode 100644
index 4bc1c92..0000000
--- a/docs/01_information.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Information: Network design
-
-## Default Information
-
-- Real Network range: `10.0.3.0/22` / `fde4:db8::/8`
-- Overlay Network range: `198.18.0.0/16` / `2001:0db8:c0ff:ee00::/64`
-
-| Device | Information |
-| :--- | ---: |
-| Echoman Server IPv4 address | `10.0.3.95/22` |
-| Echoman Server IPv6 address | `fde4:db8::0395/8` |
-| Echoman Server UDP connection port | `30000` |
-| Echoman Server TUN/TAP interface name | `echoman_tun` |
-| Echoman Server Virtual IPv4 address | `198.18.9.10/16` |
-| Echoman Server Virtual IPv6 address | `2001:db8:c0ff:ee00:0910:0910:0910:0910/64` |
-
-| Device | Information |
-| :--- | ---: |
-| Echoman Client IPv4 address | `10.0.3.96/22` |
-| Echoman Client IPv4 address | `fde4:db8::0396/8` |
-| Echoman Client UDP connection port | `30000` |
-| Echoman Client TUN/TAP interface name | `echoman_tun` |
-| Echoman Client Virtual IPv4 address | `198.18.x.x/16` |
-| Echoman Client Virtual IPv6 address | `2001:db8:c0ff:ee00:xxxx:xxxx:xxxx:xxxx/64` |
-
-## TUN/TAP を介したecho
-- ICMPv4
-
-
-- UDPv4
-
diff --git a/docs/02_application.md b/docs/02_application.md
deleted file mode 100644
index d4da0a5..0000000
--- a/docs/02_application.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Application: An application that communicates over the overlay network
-
-## 🎶 Chorus: echoman test application
-- Chorusは、echomanを使用したオーバーレイネットワーク通信をテストするための検証アプリケーション。
-- ポート番号は、それぞれ仮想インターフェースにバインドされた`30910 (UDP)`番を使用する。
-- UDP Request packet (`Ping`) をサーバに送信すると、クライアントにUDP Response packet (`Pong`) が返される。
-
-## Design
-```
-Client Server
-+-------------------------------------+ +-------------------------------------+
-| +--------------+ | | +--------------+ |
-| | App (Chorus) | | | | App (Chorus) | |
-| +--------------+ | | +--------------+ |
-| 198.18.x.x:30910 | | 198.18.9.10:30910 |
-| | | | | |
-| +--------------+ +--------------+ | | +--------------+ +--------------+ |
-| | TUN/TAP | | Real I/F | | UDP tunnel | | Real I/F | | TUN/TAP | |
-| | 198.18.x.x |---| 10.0.3.96 |=|============|=| 10.0.3.95 |---| 198.18.9.10 | |
-| +--------------+ +--------------+ | | +--------------+ +--------------+ |
-| 0.0.0.0:30000 | | 0.0.0.0:30000 |
-+-------------------------------------+ +-------------------------------------+
-```
-
-## README !!
-- "TUN - Application" 間のパケットを操作するのがめんどくさい👊
- - クライアントの動作
- - Chorusは直接、仮想インターフェースに対して Rawsocket を開き、パケットを直接書き込む
- - サーバの動作
- - まず、宛先パケットが `198.18.9.10:30910 (Chorus packet)` であるかどうかを判断する
- - 次に、実インターフェースから受信したパケットを仮想インターフェースに対してそのまま書き込む
- - 最後に、仮想インターフェースへの書き込みに成功すると、UDPレスポンスパケットを生成して、実インターフェースに書き込む
-- ソースコード
-```go
-/*************************************************************************************
- * README: description for Chorus.app *
-**************************************************************************************
- * Checking the TUN -> Application packet flow using source code is complicated.
- * - For the time being, I will check with wireshark.app.
- * Thefore, if the write to TUN succeeds, we generate and return a response message.
- * - Write the message generated at this time directly to the Real interface.
- * ### Judgment method ###
- * - If the destination is "198.18.9.10:30910", judge it as chorus.app and return the message.
- * - And, return a response to the UDP packet received from the client.
-*************************************************************************************/
-if net.ParseIP(device.Tun.VIP).To4().Equal(dstIP) && golayers.UDPPort(uint16(device.ChorusPort)) == dstPort {
- logger.LogDebug("Receive chorus message", "chrous", "success")
- res := chorus.GenerateUDPResponsePacket(buf)
- if _, err := device.Peer.ConnUDP.WriteToUDP(res, &device.Peer.PeerEndPoint); err != nil {
- logger.LogErr("[Failed] Send chorus message", "error", err)
- } else {
- logger.LogDebug("Send chorus message", "chrous", "success")
- }
-}
-```
diff --git a/docs/03_usage.md b/docs/03_usage.md
deleted file mode 100644
index 103c63f..0000000
--- a/docs/03_usage.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Usage: How to start echoman
-
-## Requirement
-- **⚠️WARNING**:https://docs.docker.com/desktop/previous-versions/3.x-mac/#new-9
-
-> First version of docker compose (as an alternative to the existing docker-compose). Supports some basic commands but not the complete functionality of docker-compose yet.
-
-| Languages / Frameworks | Version |
-| :--- | ---: |
-| Golang | 1.19.1 |
-| Docker Desktop | 4.12.0 |
-| docker | 20.10.17 |
-| docker-compose | 1.29.2 |
-
-## Usage
-```sh
-### envをコピー
-$ cp server/.env{.sample,}
-$ cp client/.env{.sample,}
-
-### .envの中身を環境に合わせて書き換える
-※注意: Docker networkではMACアドレスはランダムに生成されます
-
-### docker-composeを起動
-$ make up
-
-### 実行
----
-### 1枚目のTerminal: Echoman server を起動
-$ make exec/server
-# make run
-
-### 2枚目のTerminal: Echoman client を起動
-$ make exec/client
-# make run
----
-```
-
-## UDPパケットの生成
-- デフォルトでUDPパケットを生成しない場合、コメントアウトして下さい。
-> ./echoman/client/exec/run.go
-
-```go
-for {
- <-t.C
- device.NewChorusUDPPacket() // If you want to generate UDP packets, please uncomment here.
-}
-```
diff --git a/docs/04_appendix.md b/docs/04_appendix.md
deleted file mode 100644
index 5f07ffd..0000000
--- a/docs/04_appendix.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Appendix: About sockets
-
-## Standard socket / Raw socket
-
-
-- ソケット関数
-
-| args | syscall |
-| :--- | :---: |
-| Domain | `AF_PACKET` |
-| Type | `SOCK_RAW` |
-| Protocols | `IPPROTO_RAW` |
-
-- L3~ をRawsocketで操作
-```go
-// ### 送信ソケットの生成
-func SendIPv4RawSocket(dip string) (int, error) {
- fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
- if err != nil {
- return -1, err
- }
-
- ip := net.ParseIP(dip)
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
- }
-
- if err = syscall.Bind(fd, &addr); err != nil {
- return -1, err
- }
-
- return fd, nil
-}
-
-// 受信ソケットの生成
-func RecvIPv4RawSocket(sip string) (int, error) {
- fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
- if err != nil {
- return -1, err
- }
-
- ip := net.ParseIP(sip)
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
- }
-
- if err = syscall.Bind(fd, &addr); err != nil {
- return -1, err
- }
-
- return fd, nil
-}
-
-// IPv4パケット(L3~)の送信
-func SendPacket4(fd int, b []byte, dip []byte) error {
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{dip[0], dip[1], dip[2], dip[3]},
- }
-
- if err := syscall.Sendto(fd, b, 0, &addr); err != nil {
- return err
- }
-
- return nil
-}
-```
diff --git a/docs/img/icmpv4.png b/docs/img/icmpv4.png
deleted file mode 100644
index f7f0cda..0000000
Binary files a/docs/img/icmpv4.png and /dev/null differ
diff --git a/docs/img/socket.png b/docs/img/socket.png
deleted file mode 100644
index 94fcb1d..0000000
Binary files a/docs/img/socket.png and /dev/null differ
diff --git a/docs/img/udpv4.png b/docs/img/udpv4.png
deleted file mode 100644
index df7bc82..0000000
Binary files a/docs/img/udpv4.png and /dev/null differ
diff --git a/server/.env.sample b/server/.env.sample
index 9fe4089..92af0b2 100644
--- a/server/.env.sample
+++ b/server/.env.sample
@@ -1,15 +1,8 @@
-DEBUG_MODE=true
-VIRTUAL_IP_TYPE=4
-
LOCAL_INTERFACE=eth0
+LOCAL_UDP_PORT=30005
PEER_IPV4_ADDRESS=10.0.3.96
-PEER_IPV6_ADDRESS=fde4:db8::0396
-PEER_UDP_PORT=30000
-
-TUN_INTERFACE_NAME=echoman_tun
+PEER_MAC_ADDRESS=02:42:0a:00:03:60
+PEER_UDP_PORT=30006
-ECHOMAN_SERVER_IPV4_TUN=198.18.9.10
-ECHOMAN_SERVER_IPV6_TUN=2001:db8:c0ff:ee00:0910:0910:0910:0910
-
-CHROUS_PORT=30910
+DEBUG_MODE=true
diff --git a/server/Makefile b/server/Makefile
index f6b0246..8c36964 100644
--- a/server/Makefile
+++ b/server/Makefile
@@ -8,8 +8,7 @@ GODOC=$(GOCMD)doc
GOLANGCI=golangci-lint
DUMPCMD=tcpdump
-INTERFACE_REAL=eth0
-INTERFACE_VIRTUAL=echoman_tun
+INTERFACE=eth0
@@ -43,17 +42,11 @@ coverage: ## coverage
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out -o cover.html
-dump-real: ## dump packet
- $(DUMPCMD) -i ${INTERFACE_REAL}
+dump: ## dump packet
+ $(DUMPCMD) -i ${INTERFACE}
-dump-virtual: ## dump packet
- $(DUMPCMD) -i ${INTERFACE_VIRTUAL}
-
-dump-real/out: ## dump packet and output to file
- $(DUMPCMD) -i ${INTERFACE_REAL} -w ./debug/dumpfile-server-real.pcapng
-
-dump-virtual/out: ## dump packet and output to file
- $(DUMPCMD) -i ${INTERFACE_VIRTUAL} -w ./debug/dumpfile-server-virtual.pcapng
+dump/out: ## dump packet and output to file
+ $(DUMPCMD) -i ${INTERFACE} -w ./debug/dumpfile-server.pcapng
listen: ## check listen port
lsof -i -P
diff --git a/server/chorus/generate_response.go b/server/chorus/generate_response.go
deleted file mode 100644
index aafbf53..0000000
--- a/server/chorus/generate_response.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package chorus
-
-import (
- "encoding/binary"
-
- "github.com/GotoRen/echoman/server/internal/logger"
- "github.com/GotoRen/echoman/server/layers"
- "github.com/google/gopacket"
- golayers "github.com/google/gopacket/layers"
-)
-
-// GenerateUDPResponsePacket generates udp response packet.
-func GenerateUDPResponsePacket(req []byte) []byte {
- data := []byte("Pong")
-
- // swap source and destination information
- srcIPv4Addr := req[layers.IPv4offsetDst : layers.IPv4offsetDst+layers.DstIPv4Length]
- dstIPv4Addr := req[layers.IPv4offsetSrc : layers.IPv4offsetSrc+layers.SrcIPv4Length]
- srcPort := binary.BigEndian.Uint16(req[layers.DstUDPPortOffset : layers.DstUDPPortOffset+layers.DstUDPLength])
- dstPort := binary.BigEndian.Uint16(req[layers.SrcUDPPortOffset : layers.SrcUDPPortOffset+layers.SrcUDPLength])
-
- ip := golayers.IPv4{
- Version: 4,
- Protocol: golayers.IPProtocolUDP,
- SrcIP: srcIPv4Addr,
- DstIP: dstIPv4Addr,
- }
-
- udp := golayers.UDP{
- SrcPort: golayers.UDPPort(srcPort),
- DstPort: golayers.UDPPort(dstPort),
- }
-
- // fmt.Println("[DEBUG] srcIPv4Addr:", srcIPv4Addr)
- // fmt.Println("[DEBUG] dstIPv4Addr:", dstIPv4Addr)
- // fmt.Println("[DEBUG] srcPort:", srcPort)
- // fmt.Println("[DEBUG] dstPort:", dstPort)
-
- // calculating checksum
- if err := udp.SetNetworkLayerForChecksum(&ip); err != nil {
- logger.LogErr("udp set error", "error", err)
- return nil
- }
-
- options := gopacket.SerializeOptions{
- ComputeChecksums: true,
- FixLengths: true,
- }
-
- buffer := gopacket.NewSerializeBuffer()
-
- if err := gopacket.SerializeLayers(buffer, options,
- &ip,
- &udp,
- gopacket.Payload(data),
- ); err != nil {
- logger.LogErr("Serialize error", "error", err)
- return nil
- }
-
- outgoingPacket := buffer.Bytes()
-
- return outgoingPacket
-}
-
-// func NewICMPv4ReplayPacket(req []byte) []byte {
-// // swap source and destination information
-// dstMacAddr := net.HardwareAddr(req[layers.SrcMACAddrOffset : layers.SrcMACAddrOffset+layers.SrcMacLength])
-// srcMacAddr := net.HardwareAddr(req[layers.DstMACAddrOffset : layers.DstMACAddrOffset+layers.DstMacLength])
-// srcIPv4Addr := req[layers.DstIPv4AddrOffset : layers.DstIPv4AddrOffset+layers.DstIPv4Length]
-// dstIPv4Addr := req[layers.SrcIPv4AddrOffset : layers.SrcIPv4AddrOffset+layers.SrcIPv4Length]
-
-// res_data := req[layers.ICMPv4Dataoffset : layers.ICMPv4Dataoffset+layers.ICMPv4DataLength+layers.ICMPv4TimeStampLength]
-
-// ether := golayers.Ethernet{
-// DstMAC: dstMacAddr,
-// SrcMAC: srcMacAddr,
-// EthernetType: golayers.EthernetTypeIPv4,
-// }
-
-// ip := golayers.IPv4{
-// Version: 4,
-// TOS: 0,
-// Length: 0,
-// Id: 0,
-// FragOffset: 0,
-// TTL: 255,
-// Protocol: golayers.IPProtocolICMPv4,
-// Checksum: 0,
-// SrcIP: srcIPv4Addr,
-// DstIP: dstIPv4Addr,
-// }
-
-// icmpv4 := golayers.ICMPv4{
-// TypeCode: golayers.CreateICMPv4TypeCode(0, 0),
-// Checksum: 0,
-// Id: 10,
-// Seq: 1,
-// }
-
-// options := gopacket.SerializeOptions{
-// ComputeChecksums: true,
-// FixLengths: true,
-// }
-
-// buffer := gopacket.NewSerializeBuffer()
-
-// if err := gopacket.SerializeLayers(buffer, options,
-// ðer,
-// &ip,
-// &icmpv4,
-// gopacket.Payload(res_data),
-// ); err != nil {
-// logger.LogErr("Serialize error", "error", err)
-// return nil
-// }
-
-// outgoingPacket := buffer.Bytes()
-
-// return outgoingPacket
-// }
diff --git a/server/cmd/main.go b/server/cmd/main.go
index e9ce4d0..b1a2f66 100644
--- a/server/cmd/main.go
+++ b/server/cmd/main.go
@@ -1,9 +1,50 @@
package main
import (
- "github.com/GotoRen/echoman/server/exec"
+ "fmt"
+ "os"
+ "syscall"
+
+ "github.com/joho/godotenv"
+
+ "github.com/GotoRen/echoman/server/internal"
+ "github.com/GotoRen/echoman/server/internal/logger"
)
+func init() {
+ err := godotenv.Load()
+ if err != nil {
+ logger.LogErr("Error loading .env file", "error", err)
+ }
+}
+
func main() {
- exec.Run()
+ logger.InitZap()
+
+ device := internal.GetDeviceInfo(os.Getenv("LOCAL_INTERFACE"))
+ fmt.Println("[INFO] Local Interface Information:", device.IfIndex)
+ fmt.Println("[INFO] Local IPv4 Address:", device.LocalIPv4)
+ fmt.Println("[INFO] Local Hardware Address:", device.LocalMAC)
+ fmt.Println("[INFO] Peer IPv4 Address:", device.Peer.PeerIPv4)
+ fmt.Println("[INFO] Peer Hardware Address:", device.Peer.PeerMAC)
+
+ device.CreateDescriptor()
+ defer syscall.Close(device.Sd4soc)
+ defer syscall.Close(device.Rv4soc)
+
+ device.ListenServer()
+
+ for {
+ buf := make([]byte, 1500)
+ size, _, err := syscall.Recvfrom(device.Rv4soc, buf, 0)
+ if err != nil {
+ fmt.Println("[ERROR] Failed to read packet:", err)
+ }
+ if size < 8 {
+ fmt.Println("error")
+ continue
+ }
+
+ device.RoutineReceiveIncoming(buf, size, device.Sd4soc)
+ }
}
diff --git a/server/debug/dumpfile-server-real.pcapng b/server/debug/dumpfile-server-real.pcapng
deleted file mode 100644
index f5b3639..0000000
Binary files a/server/debug/dumpfile-server-real.pcapng and /dev/null differ
diff --git a/server/debug/dumpfile-server-virtual.pcapng b/server/debug/dumpfile-server-virtual.pcapng
deleted file mode 100644
index 17f4dac..0000000
Binary files a/server/debug/dumpfile-server-virtual.pcapng and /dev/null differ
diff --git a/server/debug/dumpfile-server.pcapng b/server/debug/dumpfile-server.pcapng
new file mode 100644
index 0000000..0931d0f
Binary files /dev/null and b/server/debug/dumpfile-server.pcapng differ
diff --git a/server/exec/run.go b/server/exec/run.go
deleted file mode 100644
index ede3d6e..0000000
--- a/server/exec/run.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package exec
-
-import (
- "fmt"
- "os"
- "strconv"
-
- "github.com/GotoRen/echoman/server/chorus"
- "github.com/GotoRen/echoman/server/internal"
- "github.com/GotoRen/echoman/server/internal/logger"
- "github.com/joho/godotenv"
-)
-
-func Run() {
- var err error
- loadConf()
-
- device := internal.NewDevice(os.Getenv("LOCAL_INTERFACE"))
- fmt.Println("[INFO] IP version:", device.EnvIPver)
- fmt.Println("[INFO] Local IPv4:", device.LocalIPv4)
-
- device.NewPeer()
- fmt.Println("[INFO] Peer IPv4:", device.Peer.PeerEndPoint.IP)
-
- device.CreateTunInterface()
- fmt.Println("[INFO] TUN IPv4:", device.Tun.VIP)
-
- // Create Application
- //=======================================================================//
- device.ChorusPort, err = strconv.Atoi(os.Getenv("CHROUS_PORT"))
- if err != nil {
- fmt.Println(err)
- }
-
- // Listens on ports used by applications (chorus) that use the overlay network.
- chorus.Listen(device.Tun.VIP, device.ChorusPort)
- //=======================================================================//
-
- go device.RoutineSequentialReceiver()
- go device.RoutineSequentialSender()
-
- for {
- // make the main routine wait
- }
-}
-
-func loadConf() {
- err := godotenv.Load()
- if err != nil {
- logger.LogErr("Error loading .env file", "error", err)
- }
-
- logger.InitZap()
-}
diff --git a/server/go.mod b/server/go.mod
index 62b0816..799f01f 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -4,18 +4,13 @@ go 1.19
require (
github.com/google/gopacket v1.1.19
- github.com/google/uuid v1.3.0
github.com/joho/godotenv v1.4.0
- github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
- github.com/vishvananda/netlink v1.1.0
go.uber.org/zap v1.23.0
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
- golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
)
require (
- github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
- golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 // indirect
+ golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
)
diff --git a/server/go.sum b/server/go.sum
index a9cd6b2..a2cd1a4 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -4,22 +4,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
-github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
-github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
-github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
-github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
-github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
@@ -36,11 +28,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444 h1:/d2cWp6PSamH4jDPFLyO150psQdqvtoNX8Zjg3AQ31g=
-golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/server/internal/checksum.go b/server/internal/checksum.go
deleted file mode 100644
index 920793a..0000000
--- a/server/internal/checksum.go
+++ /dev/null
@@ -1,117 +0,0 @@
-package internal
-
-import (
- "encoding/binary"
- "fmt"
- "reflect"
- "strconv"
-)
-
-func paddingZero(arr []byte) []byte {
- padarr := append(arr, 0x00)
- return padarr
-}
-
-func printByteArr(arr []byte) string {
- var str string
- for _, v := range arr {
- //fmt.Printf("%#x ", v)
- str += fmt.Sprintf("%x ", v)
- }
- return str
-}
-
-func sum3BytetoLength(arr []byte) uint64 {
- length, _ := strconv.ParseUint(fmt.Sprintf("%x", arr), 16, 16)
- return length
-}
-
-func sumByteArr(arr []byte) uint {
- var sum uint
- for i := 0; i < len(arr); i++ {
- if i%2 == 0 {
- sum += uint(binary.BigEndian.Uint16(arr[i:]))
- }
- }
- //fmt.Printf("0x%x : %b\n", sum, sum)
- return sum
-}
-
-func checktoByteArr(value interface{}) {
- rv := reflect.ValueOf(value)
- rt := rv.Type()
- var arr []byte
-
- for i := 0; i < rv.NumField(); i++ {
- field := rt.Field(i)
-
- b := rv.Field(i).Interface().([]byte)
- arr = append(arr, b...)
- fmt.Printf("%s : %x\n", field.Name, b)
- }
-}
-
-// 各構造体のフィールドが持つbyteをflatな配列にする
-func toByteArr(value interface{}) []byte {
- rv := reflect.ValueOf(value)
- //rt := rv.Type()
- var arr []byte
-
- for i := 0; i < rv.NumField(); i++ {
- //field := rt.Field(i)
- //fmt.Printf("%s\n", field.Name)
- b := rv.Field(i).Interface().([]byte)
- arr = append(arr, b...)
- }
-
- return arr
-}
-
-func toByteLen(value interface{}) uint16 {
- rv := reflect.ValueOf(value)
- var arr []byte
-
- for i := 0; i < rv.NumField(); i++ {
- b := rv.Field(i).Interface().([]byte)
- arr = append(arr, b...)
- }
-
- return uint16(len(arr))
-}
-
-func UintTo2byte(data uint16) []byte {
- b := make([]byte, 2)
- binary.BigEndian.PutUint16(b, data)
- return b
-}
-
-func UintTo3byte(data uint32) []byte {
- b := make([]byte, 4)
- binary.BigEndian.PutUint32(b, data)
- return b[1:]
-}
-
-func UintTo4byte(data uint32) []byte {
- b := make([]byte, 4)
- binary.BigEndian.PutUint32(b, data)
- return b
-}
-
-func checksum(sum uint) []byte {
- // https://el.jibun.atmarkit.co.jp/hiro/2013/07/tcp-f933.html
- // 22DA6 - 20000 + 2 = 2DA8となり、2DA8をビット反転
- val := sum - (sum>>16)<<16 + (sum >> 16) ^ 0xffff
- return UintTo2byte(uint16(val))
-}
-
-func SumbyteArr(arr []byte) uint {
- return sumByteArr(arr)
-}
-
-func CalcChecksum(sum uint) []byte {
- return checksum(sum)
-}
-
-func ToPacket(value interface{}) []byte {
- return toByteArr(value)
-}
diff --git a/server/internal/conn.go b/server/internal/conn.go
deleted file mode 100644
index 6d10b54..0000000
--- a/server/internal/conn.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package internal
-
-import (
- "net"
- "strconv"
-)
-
-// makeUDPConnection makes UDP Connection.
-func makeUDPConnection(dstPort int) (connUDP *net.UDPConn, err error) {
- udpAddr, err := net.ResolveUDPAddr("udp", ":"+strconv.Itoa(dstPort))
- if err != nil {
- return nil, err
- }
-
- connUDP, err = net.ListenUDP("udp", udpAddr)
- if err != nil {
- return nil, err
- }
-
- return connUDP, nil
-}
-
-// CreateUDPConnection creates a UDP connection with the peer node.
-func CreateUDPConnection(peerUDPport int) (*net.UDPConn, error) {
- connUDP, err := makeUDPConnection(peerUDPport)
- if err != nil {
- return nil, err
- }
-
- return connUDP, nil
-}
diff --git a/server/internal/device.go b/server/internal/device.go
index b7687a7..e73c5db 100644
--- a/server/internal/device.go
+++ b/server/internal/device.go
@@ -5,82 +5,50 @@ import (
"net"
"os"
"strconv"
- "strings"
"github.com/GotoRen/echoman/server/internal/logger"
)
type Device struct {
- EnvIPver int
-
- // Real Interface
IfIndex *net.Interface
LocalIPv4 net.IP
- LocalIPv6 net.IP
+ LocalMAC net.HardwareAddr
LocalUDPPort uint16
-
- socket struct {
- sd4soc int
- rv4soc int
- }
-
- // TUN/TAP Interface
- Tun struct {
- Device *TunInterface
- VIP string
- mtu int32
- }
-
- ChorusPort int
-
- Peer *Peer
+ Sd4soc int
+ Rv4soc int
+ Peer *Peer
}
-// NewDevice defines device information.
-func NewDevice(intf string) (device *Device) {
- envIPVer, err := strconv.Atoi(os.Getenv("VIRTUAL_IP_TYPE"))
+func GetDeviceInfo(intf string) (device *Device) {
+ interfaces, err := net.Interfaces()
if err != nil {
- logger.LogErr("Unable to get VIRTUAL_IP_TYPE", "error", err)
+ log.Fatal(err)
}
- interfaces, err := net.Interfaces()
+ netInterface, err := net.InterfaceByName(intf)
if err != nil {
log.Fatal(err)
}
localIPv4addr := getServerIPv4(intf, interfaces)
if localIPv4addr == nil {
- logger.LogErr("IPv4 address is empty", "error", err)
+ log.Fatal("[ERROR]: ipv4 address is empty.")
}
- device = &Device{
- EnvIPver: envIPVer,
- LocalIPv4: localIPv4addr,
- }
-
- return device
-}
+ localMACaddr := netInterface.HardwareAddr
-// CreateTunInterface creates a TUN/TAP interface.
-func (device *Device) CreateTunInterface() {
- var err error
-
- switch device.EnvIPver {
- case 4:
- device.Tun.Device, err = NewTunInterface(os.Getenv("TUN_INTERFACE_NAME"), os.Getenv("ECHOMAN_SERVER_IPV4_TUN"), "/16")
- if err != nil {
- logger.LogErr("Failed to create Tunnel Interface Virtual IPv4", "error", err)
- }
- case 6:
- device.Tun.Device, err = NewTunInterface(os.Getenv("TUN_INTERFACE_NAME"), os.Getenv("ECHOMAN_SERVER_IPV6_TUN"), "/64")
- if err != nil {
- logger.LogErr("Failed to create Tunnel Interface Virtual IPv6", "error", err)
- }
+ localUDPport, err := strconv.Atoi(os.Getenv("LOCAL_UDP_PORT"))
+ if err != nil {
+ logger.LogErr("Type conversion failed", "error", err)
}
- if err := device.Tun.Device.Up(); err != nil {
- logger.LogErr("Failed to Tunnel up", "error", err)
+ device = &Device{
+ IfIndex: netInterface,
+ LocalIPv4: localIPv4addr,
+ LocalMAC: localMACaddr,
+ LocalUDPPort: uint16(localUDPport),
+ Peer: GerPeerInfo(),
}
- device.Tun.VIP = device.Tun.Device.address[:strings.Index(device.Tun.Device.address, "/")]
+ return device
}
diff --git a/server/internal/handle_icmpv4.go b/server/internal/handle_icmpv4.go
new file mode 100644
index 0000000..ee5997e
--- /dev/null
+++ b/server/internal/handle_icmpv4.go
@@ -0,0 +1,67 @@
+package internal
+
+import (
+ "net"
+
+ "github.com/GotoRen/echoman/server/internal/logger"
+ "github.com/GotoRen/echoman/server/layers"
+ "github.com/google/gopacket"
+ golayers "github.com/google/gopacket/layers"
+)
+
+func NewICMPv4ReplayPacket(req []byte) []byte {
+ // ここで送信元と宛先の情報を入れ替える
+ dstMacAddr := net.HardwareAddr(req[layers.SrcMACAddrOffset : layers.SrcMACAddrOffset+layers.SrcMacLength])
+ srcMacAddr := net.HardwareAddr(req[layers.DstMACAddrOffset : layers.DstMACAddrOffset+layers.DstMacLength])
+ srcIPv4Addr := req[layers.DstIPv4AddrOffset : layers.DstIPv4AddrOffset+layers.DstIPv4Length]
+ dstIPv4Addr := req[layers.SrcIPv4AddrOffset : layers.SrcIPv4AddrOffset+layers.SrcIPv4Length]
+
+ res_data := req[layers.ICMPv4Dataoffset : layers.ICMPv4Dataoffset+layers.ICMPv4DataLength+layers.ICMPv4TimeStampLength]
+
+ ether := golayers.Ethernet{
+ DstMAC: dstMacAddr,
+ SrcMAC: srcMacAddr,
+ EthernetType: golayers.EthernetTypeIPv4,
+ }
+
+ ip := golayers.IPv4{
+ Version: 4,
+ TOS: 0,
+ Length: 0,
+ Id: 0,
+ FragOffset: 0,
+ TTL: 255,
+ Protocol: golayers.IPProtocolICMPv4,
+ Checksum: 0,
+ SrcIP: srcIPv4Addr,
+ DstIP: dstIPv4Addr,
+ }
+
+ icmpv4 := golayers.ICMPv4{
+ TypeCode: golayers.CreateICMPv4TypeCode(0, 0),
+ Checksum: 0,
+ Id: 10,
+ Seq: 1,
+ }
+
+ options := gopacket.SerializeOptions{
+ ComputeChecksums: true,
+ FixLengths: true,
+ }
+
+ buffer := gopacket.NewSerializeBuffer()
+
+ if err := gopacket.SerializeLayers(buffer, options,
+ ðer,
+ &ip,
+ &icmpv4,
+ gopacket.Payload(res_data),
+ ); err != nil {
+ logger.LogErr("Serialize error", "error", err)
+ return nil
+ }
+
+ outgoingPacket := buffer.Bytes()
+
+ return outgoingPacket
+}
diff --git a/server/internal/handle_udp.go b/server/internal/handle_udp.go
new file mode 100644
index 0000000..ea05200
--- /dev/null
+++ b/server/internal/handle_udp.go
@@ -0,0 +1,73 @@
+package internal
+
+import (
+ "encoding/binary"
+ "net"
+
+ "github.com/GotoRen/echoman/server/internal/logger"
+ "github.com/GotoRen/echoman/server/layers"
+ "github.com/google/gopacket"
+ golayers "github.com/google/gopacket/layers"
+)
+
+func NewUDPResponsePacket(req []byte) []byte {
+ // ここで送信元と宛先の情報を入れ替える
+ dstMacAddr := net.HardwareAddr(req[layers.SrcMACAddrOffset : layers.SrcMACAddrOffset+layers.SrcMacLength])
+ srcMacAddr := net.HardwareAddr(req[layers.DstMACAddrOffset : layers.DstMACAddrOffset+layers.DstMacLength])
+ srcIPv4Addr := req[layers.DstIPv4AddrOffset : layers.DstIPv4AddrOffset+layers.DstIPv4Length]
+ dstIPv4Addr := req[layers.SrcIPv4AddrOffset : layers.SrcIPv4AddrOffset+layers.SrcIPv4Length]
+ srcPort := binary.BigEndian.Uint16(req[layers.DstUDPPortOffset : layers.DstUDPPortOffset+layers.DstUDPLength])
+ dstPort := binary.BigEndian.Uint16(req[layers.SrcUDPPortOffset : layers.SrcUDPPortOffset+layers.SrcUDPLength])
+
+ ether := golayers.Ethernet{
+ DstMAC: dstMacAddr,
+ SrcMAC: srcMacAddr,
+ EthernetType: golayers.EthernetTypeIPv4,
+ }
+
+ ip := golayers.IPv4{
+ Version: 4,
+ TOS: 0,
+ Length: 0,
+ Id: 0,
+ FragOffset: 0,
+ TTL: 255,
+ Protocol: golayers.IPProtocolUDP,
+ Checksum: 0,
+ SrcIP: srcIPv4Addr,
+ DstIP: dstIPv4Addr,
+ }
+
+ udp := golayers.UDP{
+ SrcPort: golayers.UDPPort(srcPort),
+ DstPort: golayers.UDPPort(dstPort),
+ }
+ data := []byte("Pong")
+
+ // calculating checksum
+ if err := udp.SetNetworkLayerForChecksum(&ip); err != nil {
+ logger.LogErr("udp set error", "error", err)
+ return nil
+ }
+
+ options := gopacket.SerializeOptions{
+ ComputeChecksums: true,
+ FixLengths: true,
+ }
+
+ buffer := gopacket.NewSerializeBuffer()
+
+ if err := gopacket.SerializeLayers(buffer, options,
+ ðer,
+ &ip,
+ &udp,
+ gopacket.Payload(data),
+ ); err != nil {
+ logger.LogErr("Serialize error", "error", err)
+ return nil
+ }
+
+ outgoingPacket := buffer.Bytes()
+
+ return outgoingPacket
+}
diff --git a/server/internal/peer.go b/server/internal/peer.go
index 7b49770..e34b1ea 100644
--- a/server/internal/peer.go
+++ b/server/internal/peer.go
@@ -9,32 +9,29 @@ import (
)
type Peer struct {
- // Network information
- PeerEndPoint net.UDPAddr
-
- // UDP connection
- ConnUDP *net.UDPConn
+ PeerIPv4 net.IP
+ PeerMAC net.HardwareAddr
+ PeerUDPPort uint16
}
-// NewPeer creates peer network information and UDP connections.
-func (device *Device) NewPeer() {
+func GerPeerInfo() (peer *Peer) {
peerIPv4addr := net.ParseIP(os.Getenv("PEER_IPV4_ADDRESS"))
- peerUDPport, err := strconv.Atoi(os.Getenv("PEER_UDP_PORT"))
+ peerMACaddr, err := net.ParseMAC(os.Getenv("PEER_MAC_ADDRESS"))
if err != nil {
- logger.LogErr("Type conversion failed", "error", err)
+ logger.LogErr("MAC address parse error", "error", err)
}
- connUDP, err := CreateUDPConnection(peerUDPport)
+ peerUDPport, err := strconv.Atoi(os.Getenv("PEER_UDP_PORT"))
if err != nil {
- logger.LogErr("Unable to establish UDP connection", "error", err)
+ logger.LogErr("Type conversion failed", "error", err)
}
- device.Peer = &Peer{
- PeerEndPoint: net.UDPAddr{
- IP: peerIPv4addr,
- Port: peerUDPport,
- },
- ConnUDP: connUDP,
+ peer = &Peer{
+ PeerIPv4: peerIPv4addr,
+ PeerMAC: peerMACaddr,
+ PeerUDPPort: uint16(peerUDPport),
}
+
+ return peer
}
diff --git a/server/internal/raw_socket.go b/server/internal/raw_socket.go
index 7f8c31b..89440f4 100644
--- a/server/internal/raw_socket.go
+++ b/server/internal/raw_socket.go
@@ -1,6 +1,7 @@
package internal
import (
+ "log"
"net"
"syscall"
@@ -11,10 +12,6 @@ func htons(host uint16) uint16 {
return (host&0xff)<<8 | (host >> 8)
}
-// ========================================================================= //
-// L2 socket
-// ========================================================================= //
-
// etherSendSock creates a new send socket for IPv4 ethernet packet.
func etherSendSock(intfIndex *net.Interface) (int, error) {
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_IP)))
@@ -57,7 +54,7 @@ func etherRecvSock(intfIndex *net.Interface) (int, error) {
return fd, nil
}
-// SendEtherPacket uses a send socket to send an ether packet.
+// SendEtherPacket uses a send socket to send an Ethernete packet.
func SendEtherPacket(fd int, b []byte) error {
if _, err := syscall.Write(fd, b); err != nil {
return err
@@ -66,82 +63,19 @@ func SendEtherPacket(fd int, b []byte) error {
return nil
}
-// RecvEtherPacket uses a receive socket to receive an ether packet.
-func RecvEtherPacket(fd int, b []byte) error {
- if _, err := syscall.Read(fd, b); err != nil {
- return err
- }
-
- return nil
-}
-
-// ========================================================================= //
-// L3 socket
-// ========================================================================= //
+// CreateDescriptor creates socket descriptor.
+func (device *Device) CreateDescriptor() {
+ var err error
-// SendIPv4RawSocket creates a raw socket for sending IPv4 packet.
-func SendIPv4RawSocket(dip string) (int, error) {
- fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
+ // send socket
+ device.Sd4soc, err = etherSendSock(device.IfIndex)
if err != nil {
- return -1, err
- }
-
- ip := net.ParseIP(dip)
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
+ logger.LogErr("Failed to open send IPv4 raw socket", "error", err)
}
- if err = syscall.Bind(fd, &addr); err != nil {
- return -1, err
- }
-
- return fd, nil
-}
-
-// RecvIPv4RawSocket creates a raw socket for receiving IPv4 packet.
-func RecvIPv4RawSocket(sip string) (int, error) {
- fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
+ // receive socket
+ device.Rv4soc, err = etherRecvSock(device.IfIndex)
if err != nil {
- return -1, err
- }
-
- ip := net.ParseIP(sip)
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
- }
-
- if err = syscall.Bind(fd, &addr); err != nil {
- return -1, err
- }
-
- return fd, nil
-}
-
-// SendPacket4 sends IPv4 packet.
-func SendPacket4(fd int, b []byte, dip []byte) error {
- addr := syscall.SockaddrInet4{
- Addr: [4]byte{dip[0], dip[1], dip[2], dip[3]},
- }
-
- if err := syscall.Sendto(fd, b, 0, &addr); err != nil {
- return err
- }
-
- return nil
-}
-
-// ========================================================================= //
-// Socket controller
-// ========================================================================= //
-
-// closeRawSocket closes opening file descriptor.
-func closeRawSocket(fd int, fdType string) {
- if fd == -1 {
- return
- }
-
- if err := syscall.Close(fd); err != nil {
- message := "Failed to close the " + fdType + " Raw socket"
- logger.LogErr(message, "error", err)
+ log.Fatal(err)
}
}
diff --git a/server/internal/read_packet.go b/server/internal/read_packet.go
index 15c6d1d..3d9882d 100644
--- a/server/internal/read_packet.go
+++ b/server/internal/read_packet.go
@@ -1,86 +1,121 @@
package internal
import (
+ "encoding/binary"
"fmt"
- "os"
"github.com/GotoRen/echoman/server/internal/logger"
+ "github.com/GotoRen/echoman/server/layers"
"github.com/google/gopacket"
golayers "github.com/google/gopacket/layers"
+ "golang.org/x/net/ipv4"
+ "golang.org/x/net/ipv6"
)
-func (device *Device) ReadIPv4Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+func (device *Device) RoutineReceiveIncoming(buf []byte, size, sd4soc int) {
+ packet := gopacket.NewPacket(buf[:size], golayers.LayerTypeEthernet, gopacket.Default)
+ eh := &layers.EtherHeader{
+ DstMacAddr: buf[layers.DstMACAddrOffset : layers.DstMACAddrOffset+layers.DstMacLength],
+ SrcMacAddr: buf[layers.SrcMACAddrOffset : layers.SrcMACAddrOffset+layers.SrcMacLength],
+ ProtoType: binary.BigEndian.Uint16(buf[layers.Protocoloffset : layers.Protocoloffset+layers.ProtocolTypeLength]),
+ }
- icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
- if icmpv4Layer != nil {
- icmpv4 := icmpv4Layer.(*golayers.ICMPv4)
- switch icmpv4.TypeCode.Type() {
- case golayers.ICMPv4TypeEchoRequest:
- fmt.Println("[DEBUG] Received ICMPv4 echo request")
- case golayers.ICMPv4TypeEchoReply:
- fmt.Println("[DEBUG] Received ICMPv4 echo replay")
- default:
- logger.LogErr("Unknown ICMPv4 packet type", "error", icmpv4.TypeCode.Type())
- os.Exit(1)
+ switch eh.ProtoType {
+ case layers.EthTypeIpv4:
+ if len(buf[layers.Etherlen:size]) < ipv4.HeaderLen {
+ logger.LogErr("Received IPv4 packet is too small", "error", len(buf[layers.Etherlen:size]))
}
- }
- udpLayer := packet.Layer(golayers.LayerTypeUDP)
- if udpLayer != nil {
- udp := udpLayer.(*golayers.UDP)
- switch udp.DstPort.LayerType() {
- case golayers.LayerTypeDHCPv4:
- fmt.Println("[DEBUG] Received DHCPv4 packet")
- case golayers.LayerTypeDNS:
- fmt.Println(("[DEBUG] Received DNS A record packet"))
- default:
- logger.LogErr("Unknown IPv4 UDP packet type", "error", udp.DstPort.LayerType())
- os.Exit(1)
+ icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
+ if icmpv4Layer != nil {
+ icmpv4 := icmpv4Layer.(*golayers.ICMPv4)
+ switch icmpv4.TypeCode.Type() {
+ case golayers.ICMPv4TypeEchoRequest:
+ fmt.Println("[INFO] Received ICMPv4 echo request")
+ icmpv4res := NewICMPv4ReplayPacket(buf)
+ if err := SendEtherPacket(device.Sd4soc, icmpv4res); err != nil {
+ logger.LogErr("Filed to send ether pakcet", "error", err)
+ } else {
+ fmt.Println("[INFO] Generate ICMPv4 echo replay packet")
+ }
+ case golayers.ICMPv4TypeEchoReply:
+ fmt.Println("[INFO] Received ICMPv4 echo replay")
+ default:
+ logger.LogErr("Unknown ICMPv4 packet type", "error", icmpv4.TypeCode.Type())
+ }
}
- }
-}
-func (device *Device) ReadIPv6Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv6, gopacket.Default)
+ udpLayer := packet.Layer(golayers.LayerTypeUDP)
+ if udpLayer != nil {
+ udp := udpLayer.(*golayers.UDP)
+ switch udp.DstPort.LayerType() {
+ case golayers.LayerTypeDHCPv4:
+ logger.LogDebug("Received DHCPv4 packet", "DHCPv4", udp.DstPort.LayerType())
+ case golayers.LayerTypeDNS:
+ logger.LogDebug("Received DNS A record packet", "DNS", udp.DstPort.LayerType())
+ default:
+ if udp.DstPort == golayers.UDPPort(device.LocalUDPPort) {
+ // Echoman requst
+ layers.DebugUDPMessage(buf)
+ udpres := NewUDPResponsePacket(buf)
+ if err := SendEtherPacket(device.Sd4soc, udpres); err != nil {
+ logger.LogErr("Filed to send ether pakcet", "error", err)
+ } else {
+ layers.DebugUDPMessage(udpres)
+ }
+ } else if udp.DstPort == golayers.UDPPort(device.Peer.PeerUDPPort) {
+ // Echoman response
+ // Do nothing.
+ } else {
+ logger.LogErr("Unknown IPv4 UDP packet type", "error", udp.DstPort)
+ }
+ }
+ }
+ case layers.EthTypeIpv6:
+ if len(buf[layers.Etherlen:size]) < ipv6.HeaderLen {
+ logger.LogErr("Received IPv6 packet is too small", "error", len(buf[layers.Etherlen:size]))
+ }
- icmpv6Layer := packet.Layer(golayers.LayerTypeICMPv6)
- if icmpv6Layer != nil {
- icmpv6 := icmpv6Layer.(*golayers.ICMPv6)
- switch icmpv6.TypeCode.Type() {
- case golayers.ICMPv6TypeDestinationUnreachable:
- fmt.Println("[DEBUG] Received ICMPv6 Destination Unreachable")
- case golayers.ICMPv6TypeEchoRequest:
- fmt.Println("[DEBUG] Received ICMPv6 echo request")
- case golayers.ICMPv6TypeEchoReply:
- fmt.Println("[DEBUG] Received ICMPv6 echo replay")
- case golayers.ICMPv6TypeRouterSolicitation:
- fmt.Println("[DEBUG] Received Router Solicitation")
- case golayers.ICMPv6TypeRouterAdvertisement:
- fmt.Println("[DEBUG] Received Router Advertisement")
- case golayers.ICMPv6TypeNeighborSolicitation:
- fmt.Println("[DEBUG] Received Neighbor Solicitation")
- case golayers.ICMPv6TypeNeighborAdvertisement:
- fmt.Println("[DEBUG] Received Neighbor Advertisement")
- case golayers.ICMPv6TypeMLDv2MulticastListenerReportMessageV2:
- fmt.Println("[DEBUG] Received Multicast ListenerReport MessageV2")
- default:
- logger.LogErr("Unknown ICMPv6 packet type", "error", icmpv6.TypeCode.Type())
- os.Exit(1)
+ icmpv6Layer := packet.Layer(golayers.LayerTypeICMPv6)
+ if icmpv6Layer != nil {
+ icmpv6 := icmpv6Layer.(*golayers.ICMPv6)
+ switch icmpv6.TypeCode.Type() {
+ case golayers.ICMPv6TypeDestinationUnreachable:
+ fmt.Println("[ERROR] Received ICMPv6 Destination Unreachable")
+ case golayers.ICMPv6TypeEchoRequest:
+ logger.LogDebug("Received ICMPv6 echo request", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeEchoReply:
+ logger.LogDebug("Received ICMPv6 echo replay", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeRouterSolicitation:
+ logger.LogDebug("Received Router Solicitation", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeRouterAdvertisement:
+ logger.LogDebug("Received Router Advertisement", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeNeighborSolicitation:
+ logger.LogDebug("Received Neighbor Solicitation", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeNeighborAdvertisement:
+ logger.LogDebug("Received Neighbor Advertisement", "ICMPv6", icmpv6.TypeCode.Type())
+ case golayers.ICMPv6TypeMLDv2MulticastListenerReportMessageV2:
+ logger.LogDebug("Received Multicast ListenerReport MessageV2", "ICMPv6", icmpv6.TypeCode.Type())
+ default:
+ logger.LogErr("Unknown ICMPv6 packet type", "error", icmpv6.TypeCode.Type())
+ }
}
- }
- udpLayer := packet.Layer(golayers.LayerTypeUDP)
- if udpLayer != nil {
- udp := udpLayer.(*golayers.UDP)
- switch udp.DstPort.LayerType() {
- case golayers.LayerTypeDHCPv6:
- fmt.Println(("[DEBUG] Received DHCPv6 packet"))
- case golayers.LayerTypeDNS:
- fmt.Println(("[DEBUG] Received DNS AAAA record packet"))
- default:
- logger.LogErr("Unknown IPv6 UDP packet type", "error", udp.DstPort.LayerType())
- os.Exit(1)
+ udpLayer := packet.Layer(golayers.LayerTypeUDP)
+ if udpLayer != nil {
+ udp := udpLayer.(*golayers.UDP)
+ switch udp.DstPort.LayerType() {
+ case golayers.LayerTypeDHCPv6:
+ logger.LogDebug("Received DHCPv6 packet", "DHCPv6", udp.DstPort.LayerType())
+ case golayers.LayerTypeDNS:
+ logger.LogDebug("Received DNS AAAA record packet", "DNS", udp.DstPort.LayerType())
+ default:
+ logger.LogErr("Unknown IPv6 UDP packet type", "error", udp.DstPort.LayerType())
+ }
}
+ case layers.EthTypeArp:
+ fmt.Println("[INFO] Received ARP packet")
+ default:
+ logger.LogErr("Detect unknown protocol version", "error", eh.ProtoType)
}
}
diff --git a/server/internal/receive.go b/server/internal/receive.go
deleted file mode 100644
index a294b3d..0000000
--- a/server/internal/receive.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package internal
-
-import (
- "encoding/binary"
- "net"
-
- "github.com/GotoRen/echoman/server/chorus"
- "github.com/GotoRen/echoman/server/internal/logger"
- "github.com/GotoRen/echoman/server/layers"
- golayers "github.com/google/gopacket/layers"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-// RoutineSequentialReceiver forwards the peer's packets obtained from
-// the real interface to the virtual interface.
-func (device *Device) RoutineSequentialReceiver() {
- for {
- buf := make([]byte, 1500)
- size, _, err := device.Peer.ConnUDP.ReadFrom(buf)
- if err != nil {
- logger.LogErr("Failed to receive UDP packet", "error", err)
- }
-
- if size == 0 {
- logger.LogErr("Received packet is too small", "error", size)
- continue
- }
-
- switch buf[0] >> 4 {
- case ipv4.Version:
- if len(buf) < ipv4.HeaderLen {
- logger.LogErr("Received IPv4 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- dstIP := net.IP(buf[layers.IPv4offsetDst : layers.IPv4offsetDst+net.IPv4len]).To4()
- dstPort := golayers.UDPPort(binary.BigEndian.Uint16(buf[layers.DstUDPPortOffset : layers.DstUDPPortOffset+layers.DstUDPLength]))
-
- // fmt.Println("[DEBUG] Peer IPv4 Address", dstIP)
- // fmt.Println("[DEBUG] Peer IPv4 Port:", dstPort)
- // fmt.Println("[DEBUG] Chrous app IPv4:", net.ParseIP(device.Tun.VIP).To4())
- // fmt.Println("[DEBUG] Chrous app Port:", golayers.UDPPort(uint16(device.ChrousPort)))
-
- if _, err := device.Tun.Device.Tun.Write(buf); err != nil {
- logger.LogErr("Failed to write to tun/tap interface", "error", err)
- } else {
- /*************************************************************************************
- * README: description for Chorus.app *
- **************************************************************************************
- * Checking the TUN -> Application packet flow using source code is complicated.
- * - For the time being, I will check with wireshark.app.
- * Thefore, if the write to TUN succeeds, we generate and return a response message.
- * - Write the message generated at this time directly to the Real interface.
- * ### Judgment method ###
- * - If the destination is "198.18.9.10:30910", judge it as chorus.app and return the message.
- * - And, return a response to the UDP packet received from the client.
- *************************************************************************************/
- if net.ParseIP(device.Tun.VIP).To4().Equal(dstIP) && golayers.UDPPort(uint16(device.ChorusPort)) == dstPort {
- logger.LogDebug("Receive chorus message", "chrous", "success")
- res := chorus.GenerateUDPResponsePacket(buf)
- if _, err := device.Peer.ConnUDP.WriteToUDP(res, &device.Peer.PeerEndPoint); err != nil {
- logger.LogErr("[Failed] Send chorus message", "error", err)
- } else {
- logger.LogDebug("Send chorus message", "chrous", "success")
- }
- }
- }
-
- case ipv6.Version:
- if len(buf) < ipv6.HeaderLen {
- logger.LogErr("Received IPv6 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // dst := buf[layers.IPv6offsetDst : layers.IPv6offsetDst+net.IPv6len]
- // fmt.Println("[INFO] Peer IPv6 Address", dst)
-
- device.ReadIPv6Packet(buf)
-
- if _, err := device.Tun.Device.Tun.Write(buf); err != nil {
- logger.LogErr("Failed to write to tun/tap interface", "error", err)
- }
-
- default:
- logger.LogErr("ip version error", "error", int(buf[0]>>4))
- }
- }
-}
diff --git a/server/internal/send.go b/server/internal/send.go
deleted file mode 100644
index 4307dd3..0000000
--- a/server/internal/send.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package internal
-
-import (
- "fmt"
- "os"
-
- "github.com/GotoRen/echoman/server/internal/logger"
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-// RoutineSequentialSender sends packets obtained from a virtual interface to the peer.
-func (device *Device) RoutineSequentialSender() {
- for {
- buf := make([]byte, 1500)
- size, err := device.Tun.Device.Read(buf)
- if err != nil {
- logger.LogErr("Failed to receive virtual IP packet", "error", err)
- }
-
- if size == 0 {
- logger.LogErr("Received packet is too small", "error", size)
- continue
- }
-
- switch buf[0] >> 4 {
- case ipv4.Version:
- if len(buf) < ipv4.HeaderLen {
- logger.LogErr("Received IPv4 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // fmt.Println("[DEBUG] Received IPv4 packet from TUN/TAP", buf[:size])
- // dst := buf[layers.IPv4offsetDst : layers.IPv4offsetDst+net.IPv4len]
-
- if _, err := device.Peer.ConnUDP.WriteToUDP(buf, &device.Peer.PeerEndPoint); err != nil {
- logger.LogErr("Failed to write to real interface", "error", err)
- }
-
- case ipv6.Version:
- if len(buf) < ipv6.HeaderLen {
- logger.LogErr("Received IPv6 packet is too small", "error", len(buf))
- buf = nil
- continue
- }
- // fmt.Println("[DEBUG] Received IPv6 packet from TUN/TAP", buf[:size])
- // dst := buf[layers.IPv6offsetDst : layers.IPv6offsetDst+net.IPv6len]
-
- if _, err := device.Peer.ConnUDP.WriteToUDP(buf, &device.Peer.PeerEndPoint); err != nil {
- logger.LogErr("Failed to write to real interface", "error", err)
- }
-
- default:
- fmt.Println("ip version error")
- os.Exit(1)
- }
- }
-}
diff --git a/server/chorus/listen.go b/server/internal/server.go
similarity index 60%
rename from server/chorus/listen.go
rename to server/internal/server.go
index 0d5c528..c07245d 100644
--- a/server/chorus/listen.go
+++ b/server/internal/server.go
@@ -1,4 +1,4 @@
-package chorus
+package internal
import (
"net"
@@ -6,13 +6,13 @@ import (
"github.com/GotoRen/echoman/server/internal/logger"
)
-func portConf(li string, lp int) (*net.UDPConn, error) {
+func portConf(lp uint16) (*net.UDPConn, error) {
udpAddr := &net.UDPAddr{
- IP: net.ParseIP(li),
- Port: lp,
+ IP: net.IPv4zero.To4(),
+ Port: int(lp),
}
- c, err := net.ListenUDP("udp", udpAddr)
+ c, err := net.ListenUDP("udp4", udpAddr)
if err != nil {
return nil, err
}
@@ -27,8 +27,8 @@ func listenUDPPort(c *net.UDPConn) {
}
}
-func Listen(appIP string, appPort int) {
- conn, err := portConf(appIP, appPort)
+func (device *Device) ListenServer() {
+ conn, err := portConf(device.LocalUDPPort)
if err != nil {
logger.LogErr("Failed to create connection", "error", err)
}
diff --git a/server/internal/tun.go b/server/internal/tun.go
deleted file mode 100644
index 2137cbe..0000000
--- a/server/internal/tun.go
+++ /dev/null
@@ -1,152 +0,0 @@
-package internal
-
-import (
- "fmt"
- "os/exec"
- "runtime"
-
- "github.com/GotoRen/echoman/server/internal/logger"
- "github.com/songgao/water"
- "github.com/vishvananda/netlink"
- "golang.org/x/xerrors"
-)
-
-// TunInterface manages Tunnel device.
-type TunInterface struct {
- Tun *water.Interface
- address string
-}
-
-// NewTunInterface returns Tunnel device.
-func NewTunInterface(name string, address string, prefix string) (*TunInterface, error) {
- addr := address + prefix
-
- switch runtime.GOOS {
- case "linux":
- config := water.Config{
- DeviceType: water.TUN,
- }
- config.Name = name
-
- ifce, err := water.New(config)
- if err != nil {
- return nil, err
- }
-
- iface := &TunInterface{
- Tun: ifce,
- address: addr,
- }
-
- return iface, nil
-
- case "darwin":
- ifce, err := water.New(water.Config{
- DeviceType: water.TUN,
- })
- if err != nil {
- return nil, err
- }
-
- iface := &TunInterface{
- Tun: ifce,
- address: addr,
- }
-
- return iface, nil
-
- case "windows":
- return nil, xerrors.Errorf("Windows is not supported")
- default:
- return nil, xerrors.Errorf("%s is not supported", runtime.GOOS)
- }
-}
-
-// Up function ups a virtual interface.
-func (iface *TunInterface) Up() error {
- switch runtime.GOOS {
- case "linux":
- out, err := execCmd("ip", []string{"addr", "add", iface.address, "dev", iface.Tun.Name()})
- logger.LogDebug("Add a Virtual Interface", "Virtual Interface", out)
-
- if err != nil {
- logger.LogErr("ip command add fail", "error", err)
- return err
- }
-
- set, err := execCmd("ip", []string{"link", "set", "dev", iface.Tun.Name(), "up", "mtu", "1460"})
- logger.LogDebug("Up a Virtual Interface", "Virtual Interface", set)
-
- if err != nil {
- logger.LogErr("ip command set fail", "error", err)
- return err
- }
-
- case "darwin":
- out, err := execCmd("ifconfig", []string{iface.Tun.Name(), "up"})
- logger.LogDebug("Add a Virtual Interface", "Virtual Interface", out)
-
- if err != nil {
- logger.LogErr("ifconfig fail", "error", err)
- return err
- }
-
- if tun, err := netlink.LinkByName(iface.Tun.Name()); err == nil {
- addr, err := netlink.ParseAddr(iface.address)
- if err != nil {
- logger.LogErr("Unable to parse address", "error", err)
- }
-
- if err := netlink.AddrAdd(tun, addr); err != nil {
- logger.LogErr("Unable to add IP address to linked device", "error", err)
- }
-
- // TODO: Change MTU
-
- logger.LogDebug("Check Virtual Interface Name", "Virtual Interface Name", iface.Tun.Name())
- logger.LogDebug("Check Virtual Interface Address", "Virtual Interface Address", iface.address)
- }
-
- default:
- logger.LogErr("unsupported", "error", runtime.GOOS)
- logger.LogErr("unsupported", "error", runtime.GOARCH)
- return fmt.Errorf("unsupported: %s %s", runtime.GOOS, runtime.GOARCH)
- }
-
- return nil
-}
-
-// Read function read the virtual interface.
-func (iface *TunInterface) Read(buf []byte) (int, error) {
- n, err := iface.Tun.Read(buf)
- // Read Virtual Interface.
- if err != nil {
- logger.LogErr("Failed to read virtual interface", "error", err)
- return 0, err
- }
-
- return n, nil
-}
-
-// Write function write the virtual interface.
-func (iface *TunInterface) Write(buf []byte) (int, error) {
- return iface.Tun.Write(buf)
-}
-
-// Close function closes the virtual interface.
-func (iface *TunInterface) Close() {
- if err := iface.Tun.Close(); err != nil {
- logger.LogErr("Failed to close virtual interface", "error", err)
- }
-}
-
-// execCmd executes the given arguments as a command.
-func execCmd(cmd string, args []string) (string, error) {
- execCmd := exec.Command(cmd, args...)
- if err := execCmd.Run(); err != nil {
- logger.LogErr("Unable to execute command ", "error", err.Error())
- return execCmd.String(), err
- }
-
- return execCmd.String(), nil
-}
diff --git a/server/internal/vip.go b/server/internal/vip.go
deleted file mode 100644
index 5faee69..0000000
--- a/server/internal/vip.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package internal
-
-import (
- "crypto/rand"
- "encoding/binary"
- "fmt"
- "net"
- "strings"
-
- "github.com/GotoRen/echoman/server/internal/logger"
- "github.com/google/uuid"
-)
-
-// rfc3330, rfc2544.
-// Using the Documentation addresses and prefixes.
-var VIPv4NetworkAddress string = "198.18.0.0/16"
-var VIPv6NetworkAddress string = "2001:0db8:c0ff:ee00::/64"
-
-// getVIPv4NetworkAddressInfo returns information about virtual IPv4 overlay network.
-func getVIPv4NetworkAddressInfo() (vipv4nwaddress net.IP, vipv4netmask net.IPMask, vipv4prefix string) {
- _, ipnet, err := net.ParseCIDR(VIPv4NetworkAddress)
- if err != nil {
- logger.LogErr("Unable to get Virtual IPv4 network address", "error", err)
- }
-
- vipv4nwaddress = ipnet.IP
- vipv4netmask = ipnet.Mask
- vipv4prefix = VIPv4NetworkAddress[strings.Index(VIPv4NetworkAddress, "/"):]
-
- return
-}
-
-// getVIPv6NetworkAddressInfo returns information about virtual IPv6 overlay network.
-func getVIPv6NetworkAddressInfo() (vipv6nwaddress net.IP, vipv6netmask net.IPMask, vipv6prefix string) {
- _, ipnet, err := net.ParseCIDR(VIPv6NetworkAddress)
- if err != nil {
- logger.LogErr("Unable to get Virtual IPv4 network address", "error", err)
- }
-
- vipv6nwaddress = ipnet.IP
- vipv6netmask = ipnet.Mask
- vipv6prefix = VIPv6NetworkAddress[strings.Index(VIPv6NetworkAddress, "/"):]
-
- return
-}
-
-// generateVirtualIPv4 is to generate virtual IPv4 address.
-func generateVirtualIPv4() (net.IP, string) {
- vipv4nwaddress, _, vipv4prefix := getVIPv4NetworkAddressInfo()
- b := make([]byte, 2)
-
-createVIPv4:
- err := binary.Read(rand.Reader, binary.BigEndian, &b)
- if err != nil {
- logger.LogErr("Failed to generate random 2 bytes for VirtualIPv4", "error", err)
- }
-
- vipv4 := net.IPv4(vipv4nwaddress[0], vipv4nwaddress[1], b[0], b[1]).To4()
-
- // TODO: If you use netip.Addr type you can use switch-case.
- // 198.18.0.0/16 => network address or 198.18.255.255/16 => broadcast address
- if vipv4.Equal(net.IPv4(vipv4nwaddress[0], vipv4nwaddress[1], 0x00, 0x00).To4()) || vipv4.Equal(net.IPv4(vipv4nwaddress[0], vipv4nwaddress[1], 0xff, 0xff).To4()) {
- goto createVIPv4
- }
-
- return vipv4, vipv4prefix
-}
-
-// generateVirtualIPv6 is to generate virtual IPv6 address.
-func generateVirtualIPv6() (net.IP, string) {
- vipv6nwaddress, _, vipv6prefix := getVIPv6NetworkAddressInfo()
-
- u, err := uuid.NewRandom()
- if err != nil {
- logger.LogErr("Failed to generate UUID for VirtualIPv6", "error", err)
- }
-
- ub, err := u.MarshalBinary()
- if err != nil {
- logger.LogErr("For VirtualIPv6: Failed encode to binary format", "error", err)
- }
-
- vipv6 := net.ParseIP(strings.Replace(vipv6nwaddress.String(), "::", fmt.Sprintf(":%x:%x:%x:%x", ub[8:10], ub[10:12], ub[12:14], ub[14:16]), 1))
-
- return vipv6, vipv6prefix
-}
diff --git a/server/layers/icmpv4.go b/server/layers/icmpv4.go
index 092a20f..c0f450e 100644
--- a/server/layers/icmpv4.go
+++ b/server/layers/icmpv4.go
@@ -39,7 +39,7 @@ const (
)
func UnmarshalICMPv4Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
if icmpv4Layer != nil {
icmpv4, _ := icmpv4Layer.(*golayers.ICMPv4)
@@ -54,7 +54,7 @@ func UnmarshalICMPv4Packet(b []byte) {
}
func DebugICMPv4Message(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
icmpv4Layer := packet.Layer(golayers.LayerTypeICMPv4)
if icmpv4Layer != nil {
icmpv4, _ := icmpv4Layer.(*golayers.ICMPv4)
diff --git a/server/layers/ipv4.go b/server/layers/ipv4.go
index f85ed4a..c77147b 100644
--- a/server/layers/ipv4.go
+++ b/server/layers/ipv4.go
@@ -2,7 +2,6 @@ package layers
import (
"fmt"
- "net"
"github.com/google/gopacket"
golayers "github.com/google/gopacket/layers"
@@ -41,15 +40,13 @@ const (
DstIPv4Length = 4
)
-// IPv4 offset length.
const (
- IPv4offsetTotalLength = 2 // IPv4offsetPayloadLength is IPv4 offset payload length.
- IPv4offsetSrc = 12 // IPv4offsetSrc is IPv4 offset src length.
- IPv4offsetDst = IPv4offsetSrc + net.IPv4len // IPv4offsetDst is IPv4 offset dst length.
+ SrcIPv4AddrOffset = 26
+ DstIPv4AddrOffset = 30
)
func UnmarshalIPv4Packet(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
ipv4Layer := packet.Layer(golayers.LayerTypeIPv4)
if ipv4Layer != nil {
ipv4, _ := ipv4Layer.(*golayers.IPv4)
diff --git a/server/layers/ipv6.go b/server/layers/ipv6.go
deleted file mode 100644
index eab3021..0000000
--- a/server/layers/ipv6.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package layers
-
-import "net"
-
-// IPv6 offset length.
-const (
- IPv6offsetPayloadLength = 4 // IPv6offsetPayloadLength is IPv6 offset payload length.
- IPv6offsetSrc = 8 // IPv6offsetSrc is IPv6 offset src length.
- IPv6offsetDst = IPv6offsetSrc + net.IPv6len // IPv6offsetDst is IPv6 offset dst length.
-)
diff --git a/server/layers/udp.go b/server/layers/udp.go
index ace08bf..bb68f73 100644
--- a/server/layers/udp.go
+++ b/server/layers/udp.go
@@ -13,12 +13,12 @@ const (
)
const (
- SrcUDPPortOffset = 20
- DstUDPPortOffset = 22
+ SrcUDPPortOffset = 34
+ DstUDPPortOffset = 36
)
func UnmarshalUDPPacket(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
udpLayer := packet.Layer(golayers.LayerTypeUDP)
if udpLayer != nil {
udp, _ := udpLayer.(*golayers.UDP)
@@ -34,7 +34,7 @@ func UnmarshalUDPPacket(b []byte) {
}
func DebugUDPMessage(b []byte) {
- packet := gopacket.NewPacket(b, golayers.LayerTypeIPv4, gopacket.Default)
+ packet := gopacket.NewPacket(b, golayers.LayerTypeEthernet, gopacket.Default)
udpLayer := packet.Layer(golayers.LayerTypeUDP)
if udpLayer != nil {
udp, _ := udpLayer.(*golayers.UDP)