-
Notifications
You must be signed in to change notification settings - Fork 1
/
dpidrop.go
176 lines (148 loc) · 4.22 KB
/
dpidrop.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package netem
//
// DPI: rules to drop packets
//
import (
"bytes"
"github.com/google/gopacket/layers"
)
// DPIDropTrafficForServerEndpoint is a [DPIRule] that drops all
// the traffic towards a given server endpoint. The zero value is invalid;
// please fill all the fields marked as MANDATORY.
type DPIDropTrafficForServerEndpoint struct {
// Logger is the MANDATORY logger
Logger Logger
// ServerIPAddress is the MANDATORY server endpoint IP address.
ServerIPAddress string
// ServerPort is the MANDATORY server endpoint port.
ServerPort uint16
// ServerProtocol is the MANDATORY server endpoint protocol.
ServerProtocol layers.IPProtocol
}
var _ DPIRule = &DPIDropTrafficForServerEndpoint{}
// Filter implements DPIRule
func (r *DPIDropTrafficForServerEndpoint) Filter(
direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool) {
if !packet.MatchesDestination(r.ServerProtocol, r.ServerIPAddress, r.ServerPort) {
return nil, false
}
r.Logger.Infof(
"netem: dpi: dropping traffic for flow %s:%d %s:%d/%s because destination is %s:%d/%s",
packet.SourceIPAddress(),
packet.SourcePort(),
packet.DestinationIPAddress(),
packet.DestinationPort(),
packet.TransportProtocol(),
r.ServerIPAddress,
r.ServerPort,
r.ServerProtocol,
)
policy := &DPIPolicy{
Delay: 0,
Flags: FrameFlagDrop,
PLR: 0,
Spoofed: nil,
}
return policy, true
}
// DPIDropTrafficForTLSSNI is a [DPIRule] that drops all
// the traffic after it sees a given TLS SNI. The zero value is
// invalid; please fill all the fields marked as MANDATORY.
type DPIDropTrafficForTLSSNI struct {
// Logger is the MANDATORY logger
Logger Logger
// SNI is the MANDATORY SNI
SNI string
}
var _ DPIRule = &DPIDropTrafficForTLSSNI{}
// Filter implements DPIRule
func (r *DPIDropTrafficForTLSSNI) Filter(
direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool) {
// short circuit for the return path
if direction != DPIDirectionClientToServer {
return nil, false
}
// short circuit for UDP packets
if packet.TransportProtocol() != layers.IPProtocolTCP {
return nil, false
}
// try to obtain the SNI
sni, err := packet.parseTLSServerName()
if err != nil {
return nil, false
}
// if the packet is not offending, accept it
if sni != r.SNI {
return nil, false
}
r.Logger.Infof(
"netem: dpi: dropping traffic for flow %s:%d %s:%d/%s because SNI==%s",
packet.SourceIPAddress(),
packet.SourcePort(),
packet.DestinationIPAddress(),
packet.DestinationPort(),
packet.TransportProtocol(),
sni,
)
policy := &DPIPolicy{
Delay: 0,
Flags: FrameFlagDrop,
PLR: 0,
Spoofed: nil,
}
return policy, true
}
// DPIDropTrafficForString is a [DPIRule] that drops all
// the traffic after it sees a given string. The zero value is
// invalid; please fill all the fields marked as MANDATORY.
type DPIDropTrafficForString struct {
// Logger is the MANDATORY logger
Logger Logger
// ServerIPAddress is the MANDATORY server endpoint IP address.
ServerIPAddress string
// ServerPort is the MANDATORY server endpoint port.
ServerPort uint16
// SNI is the MANDATORY string
String string
}
var _ DPIRule = &DPIDropTrafficForString{}
// Filter implements DPIRule
func (r *DPIDropTrafficForString) Filter(
direction DPIDirection, packet *DissectedPacket) (*DPIPolicy, bool) {
// short circuit for the return path
if direction != DPIDirectionClientToServer {
return nil, false
}
// short circuit for UDP packets
if packet.TransportProtocol() != layers.IPProtocolTCP {
return nil, false
}
// make sure the remote server is filtered
if !packet.MatchesDestination(layers.IPProtocolTCP, r.ServerIPAddress, r.ServerPort) {
return nil, false
}
// short circuit in case of misconfiguration
if r.String == "" {
return nil, false
}
// if the packet is not offending, accept it
if !bytes.Contains(packet.TCP.Payload, []byte(r.String)) {
return nil, false
}
r.Logger.Infof(
"netem: dpi: dropping traffic for flow %s:%d %s:%d/%s because it contains %s",
packet.SourceIPAddress(),
packet.SourcePort(),
packet.DestinationIPAddress(),
packet.DestinationPort(),
packet.TransportProtocol(),
r.String,
)
policy := &DPIPolicy{
Delay: 0,
Flags: FrameFlagDrop,
PLR: 0,
Spoofed: nil,
}
return policy, true
}