-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathpacket.go
140 lines (130 loc) · 3.57 KB
/
packet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
"fmt"
"github.com/florianl/go-nfqueue"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"log"
"net"
"regexp"
"strings"
"time"
)
func packetHandle(queueNum int) {
config := nfqueue.Config{
NfQueue: uint16(queueNum),
MaxPacketLen: 0xFFFF,
MaxQueueLen: 0xFF,
Copymode: nfqueue.NfQnlCopyPacket,
WriteTimeout: 15 * time.Millisecond,
}
nf, err := nfqueue.Open(&config)
if err != nil {
fmt.Println("could not open nfqueue socket:", err)
return
}
defer nf.Close()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
fn := func(a nfqueue.Attribute) int {
id := *a.PacketID
var srcIP net.IP
var dstIP net.IP
log.Printf("PKT[%03d]\t\n", id)
packet := gopacket.NewPacket(*a.Payload, layers.LayerTypeIPv4, gopacket.Default)
// Get the IP layer from this packet
if ipLayer := packet.Layer(layers.LayerTypeIPv4); ipLayer != nil {
// Get actual IP data from this layer
ip, _ := ipLayer.(*layers.IPv4)
srcIP = ip.SrcIP
dstIP = ip.DstIP
log.Printf("%15s > %-15s \n", srcIP, dstIP)
}
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
ports := strings.Split(Port, ",")
reg := regexp.MustCompile(`\d+`)
sport := reg.FindString(tcp.SrcPort.String())
var matchedPort bool = false
for _, port := range ports {
if port == sport {
matchedPort = true
break
}
}
if matchedPort {
var ok1 bool = SaEnable && tcp.SYN && tcp.ACK
var ok2 bool = AEnable && tcp.ACK && !tcp.PSH && !tcp.FIN && !tcp.SYN && !tcp.RST
var ok3 bool = PaEnable && tcp.PSH && tcp.ACK
var ok4 bool = FaEnable && tcp.FIN && tcp.ACK
var windowSize uint16
if ok1 || ok2 || ok3 || ok4 {
if ok1 {
windowSize = WindowSa
log.Println("Handle SYN=1 and ACK=1")
}
if ok2 {
windowSize = WindowA
log.Println("Handle ACK=1")
}
if ok3 {
windowSize = WindowPa
log.Println("Handle PSH=1 and ACK=1")
}
if ok4 {
windowSize = WindowFa
log.Println("Handle FIN=1 and ACK=1")
}
packet.TransportLayer().(*layers.TCP).Window = windowSize
err := packet.TransportLayer().(*layers.TCP).SetNetworkLayerForChecksum(packet.NetworkLayer())
if err != nil {
log.Fatalf("SetNetworkLayerForChecksum error: %v", err)
}
buffer := gopacket.NewSerializeBuffer()
options := gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
if err := gopacket.SerializePacket(buffer, options, packet); err != nil {
log.Fatalf("SerializePacket error: %v", err)
}
packetBytes := buffer.Bytes()
log.Printf("Set TCP window size to %d", windowSize)
err = nf.SetVerdictModPacket(id, nfqueue.NfAccept, packetBytes)
if err != nil {
log.Fatalf("SetVerdictModified error: %v", err)
}
return 0
}
err := nf.SetVerdict(id, nfqueue.NfAccept)
if err != nil {
log.Fatalf("SetVerdictModified error: %v", err)
}
return 0
}
err := nf.SetVerdict(id, nfqueue.NfAccept)
if err != nil {
log.Fatalf("SetVerdictModified error: %v", err)
}
return 0
}
err := nf.SetVerdict(id, nfqueue.NfAccept)
if err != nil {
log.Fatalf("SetVerdictModified error: %v", err)
}
return 0
}
// Register your function to listen on nflqueue queue 100
err = nf.RegisterWithErrorFunc(ctx, fn, func(e error) int {
if e != nil {
log.Fatalln("RegisterWithErrorFunc Error:", e)
}
return 0
})
if err != nil {
fmt.Println(err)
return
}
<-ctx.Done()
}