|
@@ -17,6 +17,10 @@
|
|
|
*
|
|
*
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
+// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
+// Use of this source code is governed by a BSD-style
|
|
|
|
|
+// license that can be found in the LICENSE file.
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
|
|
|
|
|
Package tun is an IP packet tunnel server and client. It supports tunneling
|
|
Package tun is an IP packet tunnel server and client. It supports tunneling
|
|
@@ -982,13 +986,42 @@ type session struct {
|
|
|
// flowID identifies an IP traffic flow using the conventional
|
|
// flowID identifies an IP traffic flow using the conventional
|
|
|
// network 5-tuple. flowIDs track bidirectional flows.
|
|
// network 5-tuple. flowIDs track bidirectional flows.
|
|
|
type flowID struct {
|
|
type flowID struct {
|
|
|
- downstreamIPAddress net.IP
|
|
|
|
|
|
|
+ downstreamIPAddress [net.IPv6len]byte
|
|
|
downstreamPort uint16
|
|
downstreamPort uint16
|
|
|
- upstreamIPAddress net.IP
|
|
|
|
|
|
|
+ upstreamIPAddress [net.IPv6len]byte
|
|
|
upstreamPort uint16
|
|
upstreamPort uint16
|
|
|
protocol internetProtocol
|
|
protocol internetProtocol
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// From: https://github.com/golang/go/blob/b88efc7e7ac15f9e0b5d8d9c82f870294f6a3839/src/net/ip.go#L55
|
|
|
|
|
+var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
|
|
|
|
|
+
|
|
|
|
|
+func (f *flowID) set(
|
|
|
|
|
+ downstreamIPAddress net.IP,
|
|
|
|
|
+ downstreamPort uint16,
|
|
|
|
|
+ upstreamIPAddress net.IP,
|
|
|
|
|
+ upstreamPort uint16,
|
|
|
|
|
+ protocol internetProtocol) {
|
|
|
|
|
+
|
|
|
|
|
+ if len(downstreamIPAddress) == net.IPv4len {
|
|
|
|
|
+ copy(f.downstreamIPAddress[:], v4InV6Prefix)
|
|
|
|
|
+ copy(f.downstreamIPAddress[len(v4InV6Prefix):], downstreamIPAddress)
|
|
|
|
|
+ } else { // net.IPv6len
|
|
|
|
|
+ copy(f.downstreamIPAddress[:], downstreamIPAddress)
|
|
|
|
|
+ }
|
|
|
|
|
+ f.downstreamPort = downstreamPort
|
|
|
|
|
+
|
|
|
|
|
+ if len(upstreamIPAddress) == net.IPv4len {
|
|
|
|
|
+ copy(f.upstreamIPAddress[:], v4InV6Prefix)
|
|
|
|
|
+ copy(f.upstreamIPAddress[len(v4InV6Prefix):], upstreamIPAddress)
|
|
|
|
|
+ } else { // net.IPv6len
|
|
|
|
|
+ copy(f.upstreamIPAddress[:], upstreamIPAddress)
|
|
|
|
|
+ }
|
|
|
|
|
+ f.upstreamPort = upstreamPort
|
|
|
|
|
+
|
|
|
|
|
+ f.protocol = protocol
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
type flowState struct {
|
|
type flowState struct {
|
|
|
// Note: 64-bit ints used with atomic operations are placed
|
|
// Note: 64-bit ints used with atomic operations are placed
|
|
|
// at the start of struct to ensure 64-bit alignment.
|
|
// at the start of struct to ensure 64-bit alignment.
|
|
@@ -1101,7 +1134,9 @@ func (session *session) startTrackingFlow(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
flowState := &flowState{
|
|
flowState := &flowState{
|
|
|
- activityUpdaters: session.flowActivityUpdaterMaker(hostname, ID.upstreamIPAddress),
|
|
|
|
|
|
|
+ activityUpdaters: session.flowActivityUpdaterMaker(
|
|
|
|
|
+ hostname,
|
|
|
|
|
+ net.IP(ID.upstreamIPAddress[:])),
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if direction == packetDirectionServerUpstream {
|
|
if direction == packetDirectionServerUpstream {
|
|
@@ -2083,30 +2118,22 @@ func processPacket(
|
|
|
doFlowTracking := !doTransparentDNS && isServer
|
|
doFlowTracking := !doTransparentDNS && isServer
|
|
|
|
|
|
|
|
// TODO: verify this struct is stack allocated
|
|
// TODO: verify this struct is stack allocated
|
|
|
- var flowID flowID
|
|
|
|
|
|
|
+ var ID flowID
|
|
|
|
|
|
|
|
isTrackingFlow := false
|
|
isTrackingFlow := false
|
|
|
|
|
|
|
|
if doFlowTracking {
|
|
if doFlowTracking {
|
|
|
|
|
|
|
|
- flowID.protocol = protocol
|
|
|
|
|
-
|
|
|
|
|
if direction == packetDirectionServerUpstream {
|
|
if direction == packetDirectionServerUpstream {
|
|
|
-
|
|
|
|
|
- flowID.upstreamIPAddress = destinationIPAddress
|
|
|
|
|
- flowID.upstreamPort = destinationPort
|
|
|
|
|
- flowID.downstreamIPAddress = sourceIPAddress
|
|
|
|
|
- flowID.downstreamPort = sourcePort
|
|
|
|
|
|
|
+ ID.set(
|
|
|
|
|
+ destinationIPAddress, destinationPort, sourceIPAddress, sourcePort, protocol)
|
|
|
|
|
|
|
|
} else if direction == packetDirectionServerDownstream {
|
|
} else if direction == packetDirectionServerDownstream {
|
|
|
-
|
|
|
|
|
- flowID.upstreamIPAddress = sourceIPAddress
|
|
|
|
|
- flowID.upstreamPort = sourcePort
|
|
|
|
|
- flowID.downstreamIPAddress = destinationIPAddress
|
|
|
|
|
- flowID.downstreamPort = destinationPort
|
|
|
|
|
|
|
+ ID.set(
|
|
|
|
|
+ sourceIPAddress, sourcePort, destinationIPAddress, destinationPort, protocol)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- isTrackingFlow = session.isTrackingFlow(flowID)
|
|
|
|
|
|
|
+ isTrackingFlow = session.isTrackingFlow(ID)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Check packet source/destination is permitted; except for:
|
|
// Check packet source/destination is permitted; except for:
|
|
@@ -2132,7 +2159,8 @@ func processPacket(
|
|
|
if protocol == internetProtocolTCP {
|
|
if protocol == internetProtocolTCP {
|
|
|
|
|
|
|
|
if checkPort == 0 ||
|
|
if checkPort == 0 ||
|
|
|
- (isServer && !session.checkAllowedTCPPortFunc(flowID.upstreamIPAddress, checkPort)) {
|
|
|
|
|
|
|
+ (isServer &&
|
|
|
|
|
+ !session.checkAllowedTCPPortFunc(net.IP(ID.upstreamIPAddress[:]), checkPort)) {
|
|
|
|
|
|
|
|
metrics.rejectedPacket(direction, packetRejectTCPPort)
|
|
metrics.rejectedPacket(direction, packetRejectTCPPort)
|
|
|
return false
|
|
return false
|
|
@@ -2141,7 +2169,8 @@ func processPacket(
|
|
|
} else if protocol == internetProtocolUDP {
|
|
} else if protocol == internetProtocolUDP {
|
|
|
|
|
|
|
|
if checkPort == 0 ||
|
|
if checkPort == 0 ||
|
|
|
- (isServer && !session.checkAllowedUDPPortFunc(flowID.upstreamIPAddress, checkPort)) {
|
|
|
|
|
|
|
+ (isServer &&
|
|
|
|
|
+ !session.checkAllowedUDPPortFunc(net.IP(ID.upstreamIPAddress[:]), checkPort)) {
|
|
|
|
|
|
|
|
metrics.rejectedPacket(direction, packetRejectUDPPort)
|
|
metrics.rejectedPacket(direction, packetRejectUDPPort)
|
|
|
return false
|
|
return false
|
|
@@ -2259,9 +2288,9 @@ func processPacket(
|
|
|
|
|
|
|
|
if doFlowTracking {
|
|
if doFlowTracking {
|
|
|
if !isTrackingFlow {
|
|
if !isTrackingFlow {
|
|
|
- session.startTrackingFlow(flowID, direction, applicationData)
|
|
|
|
|
|
|
+ session.startTrackingFlow(ID, direction, applicationData)
|
|
|
} else {
|
|
} else {
|
|
|
- session.updateFlow(flowID, direction, applicationData)
|
|
|
|
|
|
|
+ session.updateFlow(ID, direction, applicationData)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|