-
Notifications
You must be signed in to change notification settings - Fork 197
Expand file tree
/
Copy pathstack_gvisor_filter.go
More file actions
113 lines (103 loc) · 3.23 KB
/
Copy pathstack_gvisor_filter.go
File metadata and controls
113 lines (103 loc) · 3.23 KB
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
//go:build with_gvisor
package tun
import (
"net/netip"
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/header"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
)
var _ stack.LinkEndpoint = (*LinkEndpointFilter)(nil)
type LinkEndpointFilter struct {
stack.LinkEndpoint
BroadcastAddress netip.Addr
Writer GVisorTun
Dispatcher *ForwardDispatcher
Inet4Address netip.Addr
Inet6Address netip.Addr
Inet4LoopbackAddress []netip.Addr
Inet6LoopbackAddress []netip.Addr
}
func (w *LinkEndpointFilter) Attach(dispatcher stack.NetworkDispatcher) {
w.LinkEndpoint.Attach(&networkDispatcherFilter{
NetworkDispatcher: dispatcher,
broadcastAddress: w.BroadcastAddress,
writer: w.Writer,
dispatcher: w.Dispatcher,
inet4Address: w.Inet4Address,
inet6Address: w.Inet6Address,
inet4LoopbackAddress: w.Inet4LoopbackAddress,
inet6LoopbackAddress: w.Inet6LoopbackAddress,
})
}
var _ stack.NetworkDispatcher = (*networkDispatcherFilter)(nil)
type networkDispatcherFilter struct {
stack.NetworkDispatcher
broadcastAddress netip.Addr
writer GVisorTun
dispatcher *ForwardDispatcher
inet4Address netip.Addr
inet6Address netip.Addr
inet4LoopbackAddress []netip.Addr
inet6LoopbackAddress []netip.Addr
}
func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
var network header.Network
if protocol == header.IPv4ProtocolNumber {
if headerPackets, loaded := pkt.Data().PullUp(header.IPv4MinimumSize); loaded {
network = header.IPv4(headerPackets)
}
} else {
if headerPackets, loaded := pkt.Data().PullUp(header.IPv6MinimumSize); loaded {
network = header.IPv6(headerPackets)
}
}
if network == nil {
w.NetworkDispatcher.DeliverNetworkPacket(protocol, pkt)
return
}
destination := AddrFromAddress(network.DestinationAddress())
if destination == w.broadcastAddress || !destination.IsGlobalUnicast() {
w.writer.WritePacket(pkt)
return
}
if w.dispatcher != nil && pkt.GSOOptions.Type == stack.GSONone && !pkt.GSOOptions.NeedsCsum {
if view, loaded := pkt.Data().PullUp(pkt.Data().Size()); loaded {
consumed := w.dispatch(protocol, destination, view)
w.dispatcher.Flush()
if consumed {
return
}
}
}
w.NetworkDispatcher.DeliverNetworkPacket(protocol, pkt)
}
func (w *networkDispatcherFilter) dispatch(protocol tcpip.NetworkProtocolNumber, destination netip.Addr, view []byte) bool {
if protocol == header.IPv4ProtocolNumber {
switch header.IPv4(view).TransportProtocol() {
case header.TCPProtocolNumber:
for _, inet4LoopbackAddress := range w.inet4LoopbackAddress {
if destination == inet4LoopbackAddress {
return false
}
}
case header.ICMPv4ProtocolNumber:
if destination == w.inet4Address {
return false
}
}
} else {
switch header.IPv6(view).TransportProtocol() {
case header.TCPProtocolNumber:
for _, inet6LoopbackAddress := range w.inet6LoopbackAddress {
if destination == inet6LoopbackAddress {
return false
}
}
case header.ICMPv6ProtocolNumber:
if destination == w.inet6Address {
return false
}
}
}
return w.dispatcher.Dispatch(view)
}