@ -7,19 +7,20 @@ import (
"net"
"os"
"path"
"regexp"
"strconv"
"strings"
"regexp"
nfqueue "github.com/subgraph/go-nfnetlink/nfqueue"
// "github.com/subgraph/go-nfnetlink"
// "github.com/subgraph/go-nfnetlink"
"github.com/subgraph/go-procsnitch"
)
const matchAny = 0
//const noAddress = uint32(0xffffffff)
var anyAddress net . IP = net . IP { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , }
var noAddress net . IP = net . IP { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff }
var anyAddress net . IP = net . IP { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
var noAddress net . IP = net . IP { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff }
type Rule struct {
id uint
@ -37,7 +38,7 @@ type Rule struct {
gid int
uname string
gname string
sandbox string
sandbox string
}
func ( r * Rule ) String ( ) string {
@ -48,6 +49,8 @@ func (r *Rule) getString(redact bool) string {
rtype := RuleActionString [ RULE_ACTION_DENY ]
if r . rtype == RULE_ACTION_ALLOW {
rtype = RuleActionString [ RULE_ACTION_ALLOW ]
} else if r . rtype == RULE_ACTION_ALLOW_TLSONLY {
rtype = RuleActionString [ RULE_ACTION_ALLOW_TLSONLY ]
}
rmode := ""
if r . mode == RULE_MODE_SYSTEM {
@ -67,12 +70,11 @@ func (r *Rule) getString(redact bool) string {
sbox := "|"
if r . sandbox != "" {
sbox = "| SANDBOX: "+ sbox
sbox = "| " + sbox
} else {
log . Notice ( "sandbox is " , r . sandbox )
}
return fmt . Sprintf ( "%s|%s%s%s%s%s" , rtype , protostr , r . AddrString ( redact ) , rmode , rpriv , sbox )
}
@ -84,9 +86,9 @@ func (r *Rule) AddrString(redact bool) string {
} else if r . network != nil {
addr = r . network . String ( )
} else if ! addrMatchesAny ( r . addr ) && ! addrMatchesNone ( r . addr ) {
// bs := make([]byte, 4)
// binary.BigEndian.PutUint32(bs, r.addr)
// addr = fmt.Sprintf("%d.%d.%d.%d", bs[0], bs[1], bs[2], bs[3])
// bs := make([]byte, 4)
// binary.BigEndian.PutUint32(bs, r.addr)
// addr = fmt.Sprintf("%d.%d.%d.%d", bs[0], bs[1], bs[2], bs[3])
addr = r . addr . String ( )
}
@ -103,7 +105,7 @@ func (r *Rule) AddrString(redact bool) string {
type RuleList [ ] * Rule
func ( r * Rule ) match ( src net . IP , dst net . IP , dstPort uint16 , hostname string , proto string , uid , gid int , uname , gname string ) bool {
func ( r * Rule ) match ( src net . IP , dst net . IP , dstPort uint16 , hostname string , proto string , uid , gid int , uname , gname string , sandbox string ) bool {
if r . proto != proto {
return false
}
@ -117,7 +119,7 @@ func (r *Rule) match(src net.IP, dst net.IP, dstPort uint16, hostname string, pr
return false
}
log . Notice ( "comparison: " , hostname , " / " , dst , " : " , dstPort , " -> " , r . addr , " / " , r . hostname , " : " , r . port )
log . Notice ( "comparison: " , hostname , " / " , dst , " : " , dstPort , " -> " , r . addr , " / " , r . hostname , " : " , r . port )
if r . port != matchAny && r . port != dstPort {
return false
}
@ -142,7 +144,7 @@ log.Notice("comparison: ", hostname, " / ", dst, " : ", dstPort, " -> ", r.addr,
}
if proto == "icmp" {
fmt . Printf ( "network = %v, src = %v, r.addr = %x, src to4 = %x\n" , r . network , src , r . addr , binary . BigEndian . Uint32 ( src . To4 ( ) ) )
if ( r . network != nil && r . network . Contains ( src ) ) || ( r . addr . Equal ( src ) ) {
if ( r . network != nil && r . network . Contains ( src ) ) || ( r . addr . Equal ( src ) ) {
return true
}
}
@ -160,26 +162,32 @@ func (rl *RuleList) filter(pkt *nfqueue.NFQPacket, src, dst net.IP, dstPort uint
return FILTER_PROMPT
}
result := FILTER_PROMPT
sandboxed := strings . HasPrefix ( optstr , "SOCKS5|Tor / Sandbox" )
sandboxed := false
if pinfo . Sandbox != "" {
sandboxed = true
}
// sandboxed := strings.HasPrefix(optstr, "SOCKS5|Tor / Sandbox")
for _ , r := range * rl {
log . Notice ( "------------ trying match of src " , src , " against: " , r , " | " , r . saddr , " / optstr = " , optstr , "; pid " , pinfo . Pid , " vs rule pid " , r . pid )
log . Notice ( "r.saddr: " , r . saddr , "src: " , src , "sandboxed " , sandboxed , "optstr: " , optstr )
log . Notice ( "fuck " , r )
log . Notice ( "------------ trying match of src " , src , " against: " , r , " | " , r . saddr , " / optstr = " , optstr , "; pid " , pinfo . Pid , " vs rule pid " , r . pid )
log . Notice ( "r.saddr: " , r . saddr , "src: " , src , "sandboxed " , sandboxed , "optstr: " , optstr )
if r . saddr == nil && src != nil && sandboxed {
log . Notice ( "! Skipping comparison against incompatible rule types: rule src = " , r . saddr , " / packet src = " , src )
log . Notice ( "! Skipping comparison against incompatible rule types: rule src = " , r . saddr , " / packet src = " , src )
continue
} else if r . saddr == nil && src == nil && sandboxed {
continue
} else if r . saddr != nil && ! r . saddr . Equal ( src ) && r . proto != "icmp" {
log . Notice ( "! Skipping comparison of mismatching source ips" )
log . Notice ( "! Skipping comparison of mismatching source ips" )
continue
}
log . Notice ( "r.saddr = " , r . saddr , "src = " , src , "\n" )
if r . pid >= 0 && r . pid != pinfo . Pid {
//log.Notice("! Skipping comparison of mismatching PIDs")
//log.Notice("! Skipping comparison of mismatching PIDs")
continue
}
if r . match ( src , dst , dstPort , hostname , getNFQProto ( pkt ) , pinfo . UID , pinfo . GID , uidToUser ( pinfo . UID ) , gidToGroup ( pinfo . GID ) ) {
log . Notice ( "+ MATCH SUCCEEDED" )
if r . match ( src , dst , dstPort , hostname , getNFQProto ( pkt ) , pinfo . UID , pinfo . GID , uidToUser ( pinfo . UID ) , gidToGroup ( pinfo . GID ) , pinfo . Sandbox ) {
log . Notice ( "+ MATCH SUCCEEDED" )
dstStr := dst . String ( )
if FirewallConfig . LogRedact {
dstStr = STR_REDACTED
@ -196,10 +204,10 @@ log.Notice("+ MATCH SUCCEEDED")
srcStr ,
dstStr , dstPort )
if r . rtype == RULE_ACTION_DENY {
log . Warningf ( "DENIED outgoing connection attempt by %s from %s %s -> %s:%d" ,
pinfo . ExePath , r . proto ,
srcStr ,
dstStr , dstPort )
log . Warningf ( "DENIED outgoing connection attempt by %s from %s %s -> %s:%d" ,
pinfo . ExePath , r . proto ,
srcStr ,
dstStr , dstPort )
return FILTER_DENY
} else if r . rtype == RULE_ACTION_ALLOW {
result = FILTER_ALLOW
@ -208,9 +216,11 @@ log.Notice("+ MATCH SUCCEEDED")
return result
}
}
} else { log . Notice ( "+ MATCH FAILED" ) }
} else {
log . Notice ( "+ MATCH FAILED" )
}
}
log . Notice ( "--- RESULT = " , result )
log . Notice ( "--- RESULT = " , result )
return result
}
@ -235,7 +245,7 @@ func (r *Rule) parse(s string) bool {
return false
}
if ! r . parsePrivs ( parts [ 3 ] ) {
if ! r . parsePrivs ( parts [ 3 ] ) {
log . Notice ( "invalid privs " , parts [ 3 ] , " in line " , s )
return false
}
@ -245,9 +255,7 @@ func (r *Rule) parse(s string) bool {
return false
}
log . Notice ( "parsed sandbox " , parts [ 4 ] )
//fmt.Printf("uid = %v, gid = %v, user = %v, group = %v, hostname = %v\n", r.uid, r.gid, r.uname, r.gname, r.hostname)
fmt . Printf ( "uid = %v, gid = %v, user = %v, group = %v, hostname = %v, sandbox = %v\n" , r . uid , r . gid , r . uname , r . gname , r . hostname , r . sandbox )
if len ( parts ) == 6 && len ( strings . TrimSpace ( parts [ 5 ] ) ) > 0 {
r . saddr = net . ParseIP ( parts [ 5 ] )
@ -262,15 +270,7 @@ func (r *Rule) parse(s string) bool {
}
func ( r * Rule ) parseSandbox ( p string ) bool {
if p == "" {
r . sandbox = ""
return true
}
toks := strings . Split ( p , ":" )
if len ( toks ) != 2 {
return false
}
r . sandbox = toks [ 1 ]
r . sandbox = p
return true
}
@ -312,6 +312,9 @@ func (r *Rule) parseVerb(v string) bool {
case RuleActionString [ RULE_ACTION_ALLOW ] :
r . rtype = RULE_ACTION_ALLOW
return true
case RuleActionString [ RULE_ACTION_ALLOW_TLSONLY ] :
r . rtype = RULE_ACTION_ALLOW_TLSONLY
return true
case RuleActionString [ RULE_ACTION_DENY ] :
r . rtype = RULE_ACTION_DENY
return true
@ -325,7 +328,7 @@ func (r *Rule) parseTarget(t string) bool {
return false
}
sind := 0
lind := len ( addrPort ) - 1
lind := len ( addrPort ) - 1
if addrPort [ 0 ] == "udp" || addrPort [ 0 ] == "icmp" || addrPort [ 0 ] == "tcp" {
r . proto = addrPort [ 0 ]
sind ++
@ -335,7 +338,7 @@ func (r *Rule) parseTarget(t string) bool {
newAddr := strings . Join ( addrPort [ sind : lind ] , ":" )
return r . parseAddr ( newAddr ) && r . parsePort ( addrPort [ lind ] )
// return r.parseAddr(addrPort[sind]) && r.parsePort(addrPort[sind+1])
// return r.parseAddr(addrPort[sind]) && r.parsePort(addrPort[sind+1])
}
func ( r * Rule ) parseAddr ( a string ) bool {
@ -344,12 +347,12 @@ func (r *Rule) parseAddr(a string) bool {
r . addr = anyAddress
return true
}
// if strings.IndexFunc(a, unicode.IsLetter) != -1 {
// if strings.IndexFunc(a, unicode.IsLetter) != -1 {
if net . ParseIP ( a ) == nil {
r . hostname = a
return true
}
// ip := net.ParseIP(a)
// ip := net.ParseIP(a)
ip , ipnet , err := net . ParseCIDR ( a )
if err != nil || ip == nil {
ip = net . ParseIP ( a )
@ -500,7 +503,7 @@ func addrMatchesAny(addr net.IP) bool {
any := anyAddress
if addr . To4 ( ) != nil {
any = net . IP { 0 , 0 , 0 , 0 }
any = net . IP { 0 , 0 , 0 , 0 }
}
return any . Equal ( addr )
@ -510,7 +513,7 @@ func addrMatchesNone(addr net.IP) bool {
none := noAddress
if addr . To4 ( ) != nil {
none = net . IP { 0xff , 0xff , 0xff , 0xff }
none = net . IP { 0xff , 0xff , 0xff , 0xff }
}
return none . Equal ( addr )