Add IP scoping data to entity.Entity and network.Connection
This commit is contained in:
@@ -74,6 +74,8 @@ type Connection struct { //nolint:maligned // TODO: fix alignment
|
||||
// set for connections created from DNS requests. LocalIP is
|
||||
// considered immutable once a connection object has been created.
|
||||
LocalIP net.IP
|
||||
// LocalIPScope holds the network scope of the local IP.
|
||||
LocalIPScope netutils.IPScope
|
||||
// LocalPort holds the local port of the connection. It is not
|
||||
// set for connections created from DNS requests. LocalPort is
|
||||
// considered immutable once a connection object has been created.
|
||||
@@ -279,7 +281,14 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||
if inbound {
|
||||
|
||||
// inbound connection
|
||||
switch netutils.ClassifyIP(pkt.Info().Src) {
|
||||
entity = &intel.Entity{
|
||||
Protocol: uint8(pkt.Info().Protocol),
|
||||
Port: pkt.Info().SrcPort,
|
||||
}
|
||||
entity.SetIP(pkt.Info().Src)
|
||||
entity.SetDstPort(pkt.Info().DstPort)
|
||||
|
||||
switch entity.IPScope {
|
||||
case netutils.HostLocal:
|
||||
scope = IncomingHost
|
||||
case netutils.LinkLocal, netutils.SiteLocal, netutils.LocalMulticast:
|
||||
@@ -292,21 +301,15 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||
default:
|
||||
scope = IncomingInvalid
|
||||
}
|
||||
entity = &intel.Entity{
|
||||
IP: pkt.Info().Src,
|
||||
Protocol: uint8(pkt.Info().Protocol),
|
||||
Port: pkt.Info().SrcPort,
|
||||
}
|
||||
entity.SetDstPort(pkt.Info().DstPort)
|
||||
|
||||
} else {
|
||||
|
||||
// outbound connection
|
||||
entity = &intel.Entity{
|
||||
IP: pkt.Info().Dst,
|
||||
Protocol: uint8(pkt.Info().Protocol),
|
||||
Port: pkt.Info().DstPort,
|
||||
}
|
||||
entity.SetIP(pkt.Info().Dst)
|
||||
entity.SetDstPort(entity.Port)
|
||||
|
||||
// check if we can find a domain for that IP
|
||||
@@ -331,7 +334,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||
if scope == "" {
|
||||
|
||||
// outbound direct (possibly P2P) connection
|
||||
switch netutils.ClassifyIP(pkt.Info().Dst) {
|
||||
switch entity.IPScope {
|
||||
case netutils.HostLocal:
|
||||
scope = PeerHost
|
||||
case netutils.LinkLocal, netutils.SiteLocal, netutils.LocalMulticast:
|
||||
@@ -356,7 +359,6 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||
Inbound: inbound,
|
||||
// local endpoint
|
||||
IPProtocol: pkt.Info().Protocol,
|
||||
LocalIP: pkt.Info().LocalIP(),
|
||||
LocalPort: pkt.Info().LocalPort(),
|
||||
ProcessContext: getProcessContext(pkt.Ctx(), proc),
|
||||
process: proc,
|
||||
@@ -366,6 +368,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
|
||||
Started: time.Now().Unix(),
|
||||
ProfileRevisionCounter: proc.Profile().RevisionCnt(),
|
||||
}
|
||||
newConn.SetLocalIP(pkt.Info().LocalIP())
|
||||
|
||||
// Inherit internal status of profile.
|
||||
if localProfile := proc.Profile().LocalProfile(); localProfile != nil {
|
||||
@@ -380,6 +383,13 @@ func GetConnection(id string) (*Connection, bool) {
|
||||
return conns.get(id)
|
||||
}
|
||||
|
||||
// SetLocalIP sets the local IP address together with its network scope. The
|
||||
// connection is not locked for this.
|
||||
func (conn *Connection) SetLocalIP(ip net.IP) {
|
||||
conn.LocalIP = ip
|
||||
conn.LocalIPScope = netutils.GetIPScope(ip)
|
||||
}
|
||||
|
||||
// AcceptWithContext accepts the connection.
|
||||
func (conn *Connection) AcceptWithContext(reason, reasonOptionKey string, ctx interface{}) {
|
||||
if !conn.SetVerdict(VerdictAccept, reason, reasonOptionKey, ctx) {
|
||||
|
||||
@@ -2,19 +2,29 @@ package netutils
|
||||
|
||||
import "net"
|
||||
|
||||
// IP classifications
|
||||
// IPScope is the scope of the IP address.
|
||||
type IPScope int8
|
||||
|
||||
// Defined IP Scopes.
|
||||
const (
|
||||
HostLocal int8 = iota
|
||||
Invalid IPScope = iota - 1
|
||||
Undefined
|
||||
HostLocal
|
||||
LinkLocal
|
||||
SiteLocal
|
||||
Global
|
||||
LocalMulticast
|
||||
GlobalMulticast
|
||||
Invalid int8 = -1
|
||||
)
|
||||
|
||||
// ClassifyIP returns the classification for the given IP address.
|
||||
func ClassifyIP(ip net.IP) int8 { //nolint:gocognit
|
||||
// ClassifyIP returns the network scope of the given IP address.
|
||||
// Deprecated: Please use the new GetIPScope instead.
|
||||
func ClassifyIP(ip net.IP) IPScope {
|
||||
return GetIPScope(ip)
|
||||
}
|
||||
|
||||
// GetIPScope returns the network scope of the given IP address.
|
||||
func GetIPScope(ip net.IP) IPScope { //nolint:gocognit
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
// IPv4
|
||||
switch {
|
||||
@@ -76,32 +86,27 @@ func ClassifyIP(ip net.IP) int8 { //nolint:gocognit
|
||||
return Invalid
|
||||
}
|
||||
|
||||
// IPIsLocalhost returns whether the IP refers to the host itself.
|
||||
func IPIsLocalhost(ip net.IP) bool {
|
||||
return ClassifyIP(ip) == HostLocal
|
||||
// IsLocalhost returns whether the IP refers to the host itself.
|
||||
func (scope IPScope) IsLocalhost() bool {
|
||||
return scope == HostLocal
|
||||
}
|
||||
|
||||
// IPIsLAN returns true if the given IP is a site-local or link-local address.
|
||||
func IPIsLAN(ip net.IP) bool {
|
||||
switch ClassifyIP(ip) {
|
||||
case SiteLocal, LinkLocal:
|
||||
// IsLAN returns true if the scope is site-local or link-local.
|
||||
func (scope IPScope) IsLAN() bool {
|
||||
switch scope {
|
||||
case SiteLocal, LinkLocal, LocalMulticast:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IPIsGlobal returns true if the given IP is a global address.
|
||||
func IPIsGlobal(ip net.IP) bool {
|
||||
return ClassifyIP(ip) == Global
|
||||
}
|
||||
|
||||
// IPIsLinkLocal returns true if the given IP is a link-local address.
|
||||
func IPIsLinkLocal(ip net.IP) bool {
|
||||
return ClassifyIP(ip) == LinkLocal
|
||||
}
|
||||
|
||||
// IPIsSiteLocal returns true if the given IP is a site-local address.
|
||||
func IPIsSiteLocal(ip net.IP) bool {
|
||||
return ClassifyIP(ip) == SiteLocal
|
||||
// IsGlobal returns true if the scope is global.
|
||||
func (scope IPScope) IsGlobal() bool {
|
||||
switch scope {
|
||||
case Global, GlobalMulticast:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,26 +5,30 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIPClassification(t *testing.T) {
|
||||
testClassification(t, net.IPv4(71, 87, 113, 211), Global)
|
||||
testClassification(t, net.IPv4(127, 0, 0, 1), HostLocal)
|
||||
testClassification(t, net.IPv4(127, 255, 255, 1), HostLocal)
|
||||
testClassification(t, net.IPv4(192, 168, 172, 24), SiteLocal)
|
||||
testClassification(t, net.IPv4(172, 15, 1, 1), Global)
|
||||
testClassification(t, net.IPv4(172, 16, 1, 1), SiteLocal)
|
||||
testClassification(t, net.IPv4(172, 31, 1, 1), SiteLocal)
|
||||
testClassification(t, net.IPv4(172, 32, 1, 1), Global)
|
||||
func TestIPScope(t *testing.T) {
|
||||
testScope(t, net.IPv4(71, 87, 113, 211), Global)
|
||||
testScope(t, net.IPv4(127, 0, 0, 1), HostLocal)
|
||||
testScope(t, net.IPv4(127, 255, 255, 1), HostLocal)
|
||||
testScope(t, net.IPv4(192, 168, 172, 24), SiteLocal)
|
||||
testScope(t, net.IPv4(172, 15, 1, 1), Global)
|
||||
testScope(t, net.IPv4(172, 16, 1, 1), SiteLocal)
|
||||
testScope(t, net.IPv4(172, 31, 1, 1), SiteLocal)
|
||||
testScope(t, net.IPv4(172, 32, 1, 1), Global)
|
||||
}
|
||||
|
||||
func testClassification(t *testing.T, ip net.IP, expectedClassification int8) {
|
||||
c := ClassifyIP(ip)
|
||||
if c != expectedClassification {
|
||||
t.Errorf("%s is %s, expected %s", ip, classificationString(c), classificationString(expectedClassification))
|
||||
func testScope(t *testing.T, ip net.IP, expectedScope IPScope) {
|
||||
c := GetIPScope(ip)
|
||||
if c != expectedScope {
|
||||
t.Errorf("%s is %s, expected %s", ip, scopeName(c), scopeName(expectedScope))
|
||||
}
|
||||
}
|
||||
|
||||
func classificationString(c int8) string {
|
||||
func scopeName(c IPScope) string {
|
||||
switch c {
|
||||
case Invalid:
|
||||
return "invalid"
|
||||
case Undefined:
|
||||
return "undefined"
|
||||
case HostLocal:
|
||||
return "hostLocal"
|
||||
case LinkLocal:
|
||||
@@ -37,9 +41,7 @@ func classificationString(c int8) string {
|
||||
return "localMulticast"
|
||||
case GlobalMulticast:
|
||||
return "globalMulticast"
|
||||
case Invalid:
|
||||
return "invalid"
|
||||
default:
|
||||
return "unknown"
|
||||
return "undefined"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ func (table *udpTable) lookup(pktInfo *packet.Info, fast bool) (
|
||||
// attribute an incoming broadcast/multicast packet to the wrong process if
|
||||
// there are multiple processes listening on the same local port, but
|
||||
// binding to different addresses. This highly unusual for clients.
|
||||
isInboundMulticast := pktInfo.Inbound && netutils.ClassifyIP(pktInfo.LocalIP()) == netutils.LocalMulticast
|
||||
isInboundMulticast := pktInfo.Inbound && netutils.GetIPScope(pktInfo.LocalIP()) == netutils.LocalMulticast
|
||||
|
||||
// Search for the socket until found.
|
||||
for i := 1; i <= lookupRetries; i++ {
|
||||
|
||||
Reference in New Issue
Block a user