Working on portmaster restructure
This commit is contained in:
@@ -38,51 +38,57 @@ func (conn *Connection) Process() *process.Process {
|
||||
return conn.process
|
||||
}
|
||||
|
||||
// CantSay sets the connection verdict to "can't say", the connection will be further analysed.
|
||||
func (conn *Connection) CantSay() {
|
||||
if conn.Verdict != CANTSAY {
|
||||
conn.Verdict = CANTSAY
|
||||
conn.Save()
|
||||
}
|
||||
return
|
||||
// Accept accepts the connection and adds the given reason.
|
||||
func (conn *Link) Accept(reason string) {
|
||||
conn.AddReason(reason)
|
||||
conn.UpdateVerdict(ACCEPT)
|
||||
}
|
||||
|
||||
// Drop sets the connection verdict to drop.
|
||||
func (conn *Connection) Drop() {
|
||||
if conn.Verdict != DROP {
|
||||
conn.Verdict = DROP
|
||||
conn.Save()
|
||||
// Deny blocks or drops the connection depending on the connection direction and adds the given reason.
|
||||
func (conn *Link) Deny(reason string) {
|
||||
if conn.Direction {
|
||||
conn.Drop(reason)
|
||||
} else {
|
||||
conn.Block(reason)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Block sets the connection verdict to block.
|
||||
func (conn *Connection) Block() {
|
||||
if conn.Verdict != BLOCK {
|
||||
conn.Verdict = BLOCK
|
||||
conn.Save()
|
||||
}
|
||||
return
|
||||
// Block blocks the connection and adds the given reason.
|
||||
func (conn *Link) Block(reason string) {
|
||||
conn.AddReason(reason)
|
||||
conn.UpdateVerdict(BLOCK)
|
||||
}
|
||||
|
||||
// Accept sets the connection verdict to accept.
|
||||
func (conn *Connection) Accept() {
|
||||
if conn.Verdict != ACCEPT {
|
||||
conn.Verdict = ACCEPT
|
||||
// Drop drops the connection and adds the given reason.
|
||||
func (conn *Link) Drop(reason string) {
|
||||
conn.AddReason(reason)
|
||||
conn.UpdateVerdict(DROP)
|
||||
}
|
||||
|
||||
// UpdateVerdict sets a new verdict for this link, making sure it does not interfere with previous verdicts
|
||||
func (conn *Connection) UpdateVerdict(newVerdict Verdict) {
|
||||
conn.Lock()
|
||||
defer conn.Unlock()
|
||||
|
||||
if newVerdict > conn.Verdict {
|
||||
conn.Verdict = newVerdict
|
||||
conn.Save()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AddReason adds a human readable string as to why a certain verdict was set in regard to this connection
|
||||
func (conn *Connection) AddReason(newReason string) {
|
||||
func (conn *Connection) AddReason(reason string) {
|
||||
if reason == "" {
|
||||
return
|
||||
}
|
||||
|
||||
conn.Lock()
|
||||
defer conn.Unlock()
|
||||
|
||||
if conn.Reason != "" {
|
||||
conn.Reason += " | "
|
||||
}
|
||||
conn.Reason += newReason
|
||||
conn.Reason += reason
|
||||
}
|
||||
|
||||
// GetConnectionByFirstPacket returns the matching connection from the internal storage.
|
||||
@@ -92,13 +98,25 @@ func GetConnectionByFirstPacket(pkt packet.Packet) (*Connection, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var domain string
|
||||
|
||||
// if INBOUND
|
||||
// Incoming
|
||||
if direction {
|
||||
connection, ok := GetConnection(proc.Pid, "I")
|
||||
switch netutils.ClassifyIP(pkt.GetIPHeader().Src) {
|
||||
case HostLocal:
|
||||
domain = IncomingHost
|
||||
case LinkLocal, SiteLocal, LocalMulticast:
|
||||
domain = IncomingLAN
|
||||
case Global, GlobalMulticast:
|
||||
domain = IncomingInternet
|
||||
case Invalid:
|
||||
domain = IncomingInvalid
|
||||
}
|
||||
|
||||
connection, ok := GetConnection(proc.Pid, domain)
|
||||
if !ok {
|
||||
connection = &Connection{
|
||||
Domain: "I",
|
||||
Domain: domain,
|
||||
Direction: Inbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
@@ -111,12 +129,26 @@ func GetConnectionByFirstPacket(pkt packet.Packet) (*Connection, error) {
|
||||
|
||||
// get domain
|
||||
ipinfo, err := intel.GetIPInfo(pkt.FmtRemoteIP())
|
||||
|
||||
// PeerToPeer
|
||||
if err != nil {
|
||||
// if no domain could be found, it must be a direct connection
|
||||
connection, ok := GetConnection(proc.Pid, "D")
|
||||
|
||||
switch netutils.ClassifyIP(pkt.GetIPHeader().Dst) {
|
||||
case HostLocal:
|
||||
domain = PeerHost
|
||||
case LinkLocal, SiteLocal, LocalMulticast:
|
||||
domain = PeerLAN
|
||||
case Global, GlobalMulticast:
|
||||
domain = PeerInternet
|
||||
case Invalid:
|
||||
domain = PeerInvalid
|
||||
}
|
||||
|
||||
connection, ok := GetConnection(proc.Pid, domain)
|
||||
if !ok {
|
||||
connection = &Connection{
|
||||
Domain: "D",
|
||||
Domain: domain,
|
||||
Direction: Outbound,
|
||||
process: proc,
|
||||
Inspect: true,
|
||||
@@ -127,6 +159,7 @@ func GetConnectionByFirstPacket(pkt packet.Packet) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// To Domain
|
||||
// FIXME: how to handle multiple possible domains?
|
||||
connection, ok := GetConnection(proc.Pid, ipinfo.Domains[0])
|
||||
if !ok {
|
||||
|
||||
@@ -100,7 +100,7 @@ next:
|
||||
if ip == nil {
|
||||
return nil, errors.New(fmt.Sprintf("failed to parse IP: %s", peer.String()))
|
||||
}
|
||||
if !netutils.IPIsLocal(ip) {
|
||||
if !netutils.IPIsLAN(ip) {
|
||||
return ip, nil
|
||||
}
|
||||
continue next
|
||||
|
||||
@@ -80,8 +80,38 @@ func (link *Link) HandlePacket(pkt packet.Packet) {
|
||||
pkt.Drop()
|
||||
}
|
||||
|
||||
// Accept accepts the link and adds the given reason.
|
||||
func (link *Link) Accept(reason string) {
|
||||
link.AddReason(reason)
|
||||
link.UpdateVerdict(ACCEPT)
|
||||
}
|
||||
|
||||
// Deny blocks or drops the link depending on the connection direction and adds the given reason.
|
||||
func (link *Link) Deny(reason string) {
|
||||
if link.connection.Direction {
|
||||
link.Drop(reason)
|
||||
} else {
|
||||
link.Block(reason)
|
||||
}
|
||||
}
|
||||
|
||||
// Block blocks the link and adds the given reason.
|
||||
func (link *Link) Block(reason string) {
|
||||
link.AddReason(reason)
|
||||
link.UpdateVerdict(BLOCK)
|
||||
}
|
||||
|
||||
// Drop drops the link and adds the given reason.
|
||||
func (link *Link) Drop(reason string) {
|
||||
link.AddReason(reason)
|
||||
link.UpdateVerdict(DROP)
|
||||
}
|
||||
|
||||
// UpdateVerdict sets a new verdict for this link, making sure it does not interfere with previous verdicts
|
||||
func (link *Link) UpdateVerdict(newVerdict Verdict) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
|
||||
if newVerdict > link.Verdict {
|
||||
link.Verdict = newVerdict
|
||||
link.Save()
|
||||
@@ -89,14 +119,18 @@ func (link *Link) UpdateVerdict(newVerdict Verdict) {
|
||||
}
|
||||
|
||||
// AddReason adds a human readable string as to why a certain verdict was set in regard to this link
|
||||
func (link *Link) AddReason(newReason string) {
|
||||
func (link *Link) AddReason(reason string) {
|
||||
if reason == "" {
|
||||
return
|
||||
}
|
||||
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
|
||||
if link.Reason != "" {
|
||||
link.Reason += " | "
|
||||
}
|
||||
link.Reason += newReason
|
||||
link.Reason += reason
|
||||
}
|
||||
|
||||
// packetHandler sequentially handles queued packets
|
||||
|
||||
@@ -11,6 +11,7 @@ var (
|
||||
cleanDomainRegex = regexp.MustCompile("^((xn--)?[a-z0-9-_]{0,61}[a-z0-9]{1,1}\\.)*(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30}\\.[a-z]{2,}\\.)$")
|
||||
)
|
||||
|
||||
// IsValidFqdn returns whether the given string is a valid fqdn.
|
||||
func IsValidFqdn(fqdn string) bool {
|
||||
return cleanDomainRegex.MatchString(fqdn)
|
||||
}
|
||||
|
||||
@@ -4,95 +4,101 @@ package netutils
|
||||
|
||||
import "net"
|
||||
|
||||
// IP types
|
||||
// IP classifications
|
||||
const (
|
||||
hostLocal int8 = iota
|
||||
linkLocal
|
||||
siteLocal
|
||||
global
|
||||
localMulticast
|
||||
globalMulticast
|
||||
invalid
|
||||
HostLocal int8 = iota
|
||||
LinkLocal
|
||||
SiteLocal
|
||||
Global
|
||||
LocalMulticast
|
||||
GlobalMulticast
|
||||
Invalid
|
||||
)
|
||||
|
||||
func classifyAddress(ip net.IP) int8 {
|
||||
// ClassifyAddress returns the classification for the given IP address.
|
||||
func ClassifyAddress(ip net.IP) int8 {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
// IPv4
|
||||
switch {
|
||||
case ip4[0] == 127:
|
||||
// 127.0.0.0/8
|
||||
return hostLocal
|
||||
return HostLocal
|
||||
case ip4[0] == 169 && ip4[1] == 254:
|
||||
// 169.254.0.0/16
|
||||
return linkLocal
|
||||
return LinkLocal
|
||||
case ip4[0] == 10:
|
||||
// 10.0.0.0/8
|
||||
return siteLocal
|
||||
return SiteLocal
|
||||
case ip4[0] == 172 && ip4[1]&0xf0 == 16:
|
||||
// 172.16.0.0/12
|
||||
return siteLocal
|
||||
return SiteLocal
|
||||
case ip4[0] == 192 && ip4[1] == 168:
|
||||
// 192.168.0.0/16
|
||||
return siteLocal
|
||||
return SiteLocal
|
||||
case ip4[0] == 224:
|
||||
// 224.0.0.0/8
|
||||
return localMulticast
|
||||
return LocalMulticast
|
||||
case ip4[0] >= 225 && ip4[0] <= 239:
|
||||
// 225.0.0.0/8 - 239.0.0.0/8
|
||||
return globalMulticast
|
||||
return GlobalMulticast
|
||||
case ip4[0] >= 240:
|
||||
// 240.0.0.0/8 - 255.0.0.0/8
|
||||
return invalid
|
||||
return Invalid
|
||||
default:
|
||||
return global
|
||||
return Global
|
||||
}
|
||||
} else if len(ip) == net.IPv6len {
|
||||
// IPv6
|
||||
switch {
|
||||
case ip.Equal(net.IPv6loopback):
|
||||
return hostLocal
|
||||
return HostLocal
|
||||
case ip[0]&0xfe == 0xfc:
|
||||
// fc00::/7
|
||||
return siteLocal
|
||||
return SiteLocal
|
||||
case ip[0] == 0xfe && ip[1]&0xc0 == 0x80:
|
||||
// fe80::/10
|
||||
return linkLocal
|
||||
return LinkLocal
|
||||
case ip[0] == 0xff && ip[1] <= 0x05:
|
||||
// ff00::/16 - ff05::/16
|
||||
return localMulticast
|
||||
return LocalMulticast
|
||||
case ip[0] == 0xff:
|
||||
// other ff00::/8
|
||||
return globalMulticast
|
||||
return GlobalMulticast
|
||||
default:
|
||||
return global
|
||||
return Global
|
||||
}
|
||||
}
|
||||
return invalid
|
||||
return Invalid
|
||||
}
|
||||
|
||||
// IPIsLocal returns true if the given IP is a site-local or link-local address
|
||||
func IPIsLocal(ip net.IP) bool {
|
||||
switch classifyAddress(ip) {
|
||||
case siteLocal:
|
||||
// IPIsLocalhost returns whether the IP refers to the host itself.
|
||||
func IPIsLocalhost(ip net.IP) bool {
|
||||
return ClassifyAddress(ip) == HostLocal
|
||||
}
|
||||
|
||||
// IPIsLAN returns true if the given IP is a site-local or link-local address.
|
||||
func IPIsLAN(ip net.IP) bool {
|
||||
switch ClassifyAddress(ip) {
|
||||
case SiteLocal:
|
||||
return true
|
||||
case linkLocal:
|
||||
case LinkLocal:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IPIsGlobal returns true if the given IP is a global address
|
||||
// IPIsGlobal returns true if the given IP is a global address.
|
||||
func IPIsGlobal(ip net.IP) bool {
|
||||
return classifyAddress(ip) == global
|
||||
return ClassifyAddress(ip) == Global
|
||||
}
|
||||
|
||||
// IPIsLinkLocal returns true if the given IP is a link-local address
|
||||
// IPIsLinkLocal returns true if the given IP is a link-local address.
|
||||
func IPIsLinkLocal(ip net.IP) bool {
|
||||
return classifyAddress(ip) == linkLocal
|
||||
return ClassifyAddress(ip) == LinkLocal
|
||||
}
|
||||
|
||||
// IPIsSiteLocal returns true if the given IP is a site-local address
|
||||
// IPIsSiteLocal returns true if the given IP is a site-local address.
|
||||
func IPIsSiteLocal(ip net.IP) bool {
|
||||
return classifyAddress(ip) == siteLocal
|
||||
return ClassifyAddress(ip) == SiteLocal
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ import (
|
||||
)
|
||||
|
||||
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(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)
|
||||
}
|
||||
|
||||
func testClassification(t *testing.T, ip net.IP, expectedClassification int8) {
|
||||
c := classifyAddress(ip)
|
||||
c := ClassifyAddress(ip)
|
||||
if c != expectedClassification {
|
||||
t.Errorf("%s is %s, expected %s", ip, classificationString(c), classificationString(expectedClassification))
|
||||
}
|
||||
@@ -21,19 +21,19 @@ func testClassification(t *testing.T, ip net.IP, expectedClassification int8) {
|
||||
|
||||
func classificationString(c int8) string {
|
||||
switch c {
|
||||
case hostLocal:
|
||||
case HostLocal:
|
||||
return "hostLocal"
|
||||
case linkLocal:
|
||||
case LinkLocal:
|
||||
return "linkLocal"
|
||||
case siteLocal:
|
||||
case SiteLocal:
|
||||
return "siteLocal"
|
||||
case global:
|
||||
case Global:
|
||||
return "global"
|
||||
case localMulticast:
|
||||
case LocalMulticast:
|
||||
return "localMulticast"
|
||||
case globalMulticast:
|
||||
case GlobalMulticast:
|
||||
return "globalMulticast"
|
||||
case invalid:
|
||||
case Invalid:
|
||||
return "invalid"
|
||||
default:
|
||||
return "unknown"
|
||||
|
||||
@@ -9,7 +9,6 @@ type Verdict uint8
|
||||
const (
|
||||
// UNDECIDED is the default status of new connections
|
||||
UNDECIDED Verdict = iota
|
||||
CANTSAY
|
||||
ACCEPT
|
||||
BLOCK
|
||||
DROP
|
||||
@@ -20,3 +19,15 @@ const (
|
||||
Inbound = true
|
||||
Outbound = false
|
||||
)
|
||||
|
||||
// Non-Domain Connections
|
||||
const (
|
||||
IncomingHost = "IH"
|
||||
IncomingLAN = "IL"
|
||||
IncomingInternet = "II"
|
||||
IncomingInvalid = "IX"
|
||||
PeerHost = "PH"
|
||||
PeerLAN = "PL"
|
||||
PeerInternet = "PI"
|
||||
PeerInvalid = "PX"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user