|
|
@ -2,20 +2,20 @@ package sgfw
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"strconv"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
|
|
|
|
// "encoding/binary"
|
|
|
|
// "encoding/binary"
|
|
|
|
|
|
|
|
|
|
|
|
// nfnetlink "github.com/subgraph/go-nfnetlink"
|
|
|
|
// nfnetlink "github.com/subgraph/go-nfnetlink"
|
|
|
|
nfqueue "github.com/subgraph/go-nfnetlink/nfqueue"
|
|
|
|
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
|
|
|
|
nfqueue "github.com/subgraph/go-nfnetlink/nfqueue"
|
|
|
|
"github.com/subgraph/go-procsnitch"
|
|
|
|
"github.com/subgraph/go-procsnitch"
|
|
|
|
"net"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"os"
|
|
|
|
"syscall"
|
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
"unsafe"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var _interpreters = []string{
|
|
|
|
var _interpreters = []string{
|
|
|
@ -45,7 +45,9 @@ type pendingConnection interface {
|
|
|
|
srcPort() uint16
|
|
|
|
srcPort() uint16
|
|
|
|
dst() net.IP
|
|
|
|
dst() net.IP
|
|
|
|
dstPort() uint16
|
|
|
|
dstPort() uint16
|
|
|
|
|
|
|
|
sandbox() string
|
|
|
|
accept()
|
|
|
|
accept()
|
|
|
|
|
|
|
|
acceptTLSOnly()
|
|
|
|
drop()
|
|
|
|
drop()
|
|
|
|
setPrompting(bool)
|
|
|
|
setPrompting(bool)
|
|
|
|
getPrompting() bool
|
|
|
|
getPrompting() bool
|
|
|
@ -72,6 +74,10 @@ func getEmptyPInfo() *procsnitch.Info {
|
|
|
|
return &pinfo
|
|
|
|
return &pinfo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (pp *pendingPkt) sandbox() string {
|
|
|
|
|
|
|
|
return pp.pinfo.Sandbox
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (pp *pendingPkt) policy() *Policy {
|
|
|
|
func (pp *pendingPkt) policy() *Policy {
|
|
|
|
return pp.pol
|
|
|
|
return pp.pol
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -142,6 +148,13 @@ func (pp *pendingPkt) accept() {
|
|
|
|
pp.pkt.Accept()
|
|
|
|
pp.pkt.Accept()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (pp *pendingPkt) acceptTLSOnly() {
|
|
|
|
|
|
|
|
// Not implemented
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pp.pkt.SetMark(1)
|
|
|
|
|
|
|
|
pp.pkt.Accept()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (pp *pendingPkt) drop() {
|
|
|
|
func (pp *pendingPkt) drop() {
|
|
|
|
pp.pkt.SetMark(1)
|
|
|
|
pp.pkt.SetMark(1)
|
|
|
|
pp.pkt.Accept()
|
|
|
|
pp.pkt.Accept()
|
|
|
@ -196,7 +209,7 @@ func (fw *Firewall) policyForPath(path string) *Policy {
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, optstr string) {
|
|
|
|
func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, optstr string) {
|
|
|
|
|
|
|
|
|
|
|
|
/* hbytes, err := pkt.GetHWAddr()
|
|
|
|
/* hbytes, err := pkt.GetHWAddr()
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
log.Notice("Failed to get HW address underlying packet: ", err)
|
|
|
|
log.Notice("Failed to get HW address underlying packet: ", err)
|
|
|
|
} else { log.Notice("got hwaddr: ", hbytes) } */
|
|
|
|
} else { log.Notice("got hwaddr: ", hbytes) } */
|
|
|
@ -209,7 +222,7 @@ func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, o
|
|
|
|
if !FirewallConfig.LogRedact {
|
|
|
|
if !FirewallConfig.LogRedact {
|
|
|
|
log.Infof("Lookup(%s): %s", dstip.String(), name)
|
|
|
|
log.Infof("Lookup(%s): %s", dstip.String(), name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fwo := matchAgainstOzRules(srcip, dstip, dstp)
|
|
|
|
// fwo := matchAgainstOzRules(srcip, dstip, dstp)
|
|
|
|
|
|
|
|
|
|
|
|
result := p.rules.filterPacket(pkt, pinfo, srcip, name, optstr)
|
|
|
|
result := p.rules.filterPacket(pkt, pinfo, srcip, name, optstr)
|
|
|
|
switch result {
|
|
|
|
switch result {
|
|
|
@ -227,7 +240,8 @@ func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, o
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Policy) processPromptResult(pc pendingConnection) {
|
|
|
|
func (p *Policy) processPromptResult(pc pendingConnection) {
|
|
|
|
p.pendingQueue = append(p.pendingQueue, pc)
|
|
|
|
p.pendingQueue = append(p.pendingQueue, pc)
|
|
|
|
fmt.Println("processPromptResult(): p.promptInProgress = ", p.promptInProgress)
|
|
|
|
fmt.Println("im here now.. processing prompt result..")
|
|
|
|
|
|
|
|
fmt.Println("processPromptResult(): p.promptInProgress = ", p.promptInProgress)
|
|
|
|
if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) {
|
|
|
|
if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) {
|
|
|
|
p.promptInProgress = true
|
|
|
|
p.promptInProgress = true
|
|
|
|
go p.fw.dbus.prompt(p)
|
|
|
|
go p.fw.dbus.prompt(p)
|
|
|
@ -248,13 +262,13 @@ func (p *Policy) nextPending() (pendingConnection, bool) {
|
|
|
|
return nil, true
|
|
|
|
return nil, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// for len(p.pendingQueue) != 0 {
|
|
|
|
// for len(p.pendingQueue) != 0 {
|
|
|
|
for i := 0; i < len(p.pendingQueue); i++ {
|
|
|
|
for i := 0; i < len(p.pendingQueue); i++ {
|
|
|
|
if !p.pendingQueue[i].getPrompting() {
|
|
|
|
if !p.pendingQueue[i].getPrompting() {
|
|
|
|
return p.pendingQueue[i], false
|
|
|
|
return p.pendingQueue[i], false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
return nil, false
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -281,7 +295,7 @@ func (p *Policy) processNewRule(r *Rule, scope FilterScope) bool {
|
|
|
|
if scope != APPLY_ONCE {
|
|
|
|
if scope != APPLY_ONCE {
|
|
|
|
p.rules = append(p.rules, r)
|
|
|
|
p.rules = append(p.rules, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Noticef("processNewRule: ",r)
|
|
|
|
p.filterPending(r)
|
|
|
|
p.filterPending(r)
|
|
|
|
if len(p.pendingQueue) == 0 {
|
|
|
|
if len(p.pendingQueue) == 0 {
|
|
|
|
p.promptInProgress = false
|
|
|
|
p.promptInProgress = false
|
|
|
@ -291,7 +305,7 @@ func (p *Policy) processNewRule(r *Rule, scope FilterScope) bool {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Policy) parseRule(s string, add bool) (*Rule, error) {
|
|
|
|
func (p *Policy) parseRule(s string, add bool) (*Rule, error) {
|
|
|
|
log.Noticef("XXX: attempt to parse rule: |%s|\n", s)
|
|
|
|
log.Noticef("XXX: attempt to parse rule: |%s|\n", s)
|
|
|
|
r := new(Rule)
|
|
|
|
r := new(Rule)
|
|
|
|
r.pid = -1
|
|
|
|
r.pid = -1
|
|
|
|
r.mode = RULE_MODE_PERMANENT
|
|
|
|
r.mode = RULE_MODE_PERMANENT
|
|
|
@ -324,15 +338,17 @@ func (p *Policy) removeRule(r *Rule) {
|
|
|
|
func (p *Policy) filterPending(rule *Rule) {
|
|
|
|
func (p *Policy) filterPending(rule *Rule) {
|
|
|
|
remaining := []pendingConnection{}
|
|
|
|
remaining := []pendingConnection{}
|
|
|
|
for _, pc := range p.pendingQueue {
|
|
|
|
for _, pc := range p.pendingQueue {
|
|
|
|
if rule.match(pc.src(), pc.dst(), pc.dstPort(), pc.hostname(), pc.proto(), pc.procInfo().UID, pc.procInfo().GID, uidToUser(pc.procInfo().UID), gidToGroup(pc.procInfo().GID)) {
|
|
|
|
if rule.match(pc.src(), pc.dst(), pc.dstPort(), pc.hostname(), pc.proto(), pc.procInfo().UID, pc.procInfo().GID, uidToUser(pc.procInfo().UID), gidToGroup(pc.procInfo().GID), pc.procInfo().Sandbox) {
|
|
|
|
log.Infof("Adding rule for: %s", rule.getString(FirewallConfig.LogRedact))
|
|
|
|
log.Infof("Adding rule for: %s", rule.getString(FirewallConfig.LogRedact))
|
|
|
|
log.Noticef("%s > %s", rule.getString(FirewallConfig.LogRedact), pc.print())
|
|
|
|
log.Noticef("%s > %s", rule.getString(FirewallConfig.LogRedact), pc.print())
|
|
|
|
if rule.rtype == RULE_ACTION_ALLOW {
|
|
|
|
if rule.rtype == RULE_ACTION_ALLOW {
|
|
|
|
pc.accept()
|
|
|
|
pc.accept()
|
|
|
|
|
|
|
|
} else if rule.rtype == RULE_ACTION_ALLOW_TLSONLY {
|
|
|
|
|
|
|
|
pc.acceptTLSOnly()
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
srcs := pc.src().String() + ":" + strconv.Itoa(int(pc.srcPort()))
|
|
|
|
srcs := pc.src().String() + ":" + strconv.Itoa(int(pc.srcPort()))
|
|
|
|
log.Warningf("DENIED outgoing connection attempt by %s from %s %s -> %s:%d (user prompt)",
|
|
|
|
log.Warningf("DENIED outgoing connection attempt by %s from %s %s -> %s:%d (user prompt) %v",
|
|
|
|
pc.procInfo().ExePath, pc.proto(), srcs, pc.dst(), pc.dstPort)
|
|
|
|
pc.procInfo().ExePath, pc.proto(), srcs, pc.dst(), pc.dstPort, rule.rtype)
|
|
|
|
pc.drop()
|
|
|
|
pc.drop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -390,7 +406,6 @@ func printPacket(pkt *nfqueue.NFQPacket, hostname string, pinfo *procsnitch.Info
|
|
|
|
return fmt.Sprintf("(%s %s:%d -> %s:%d)", proto, SrcIp, SrcPort, name, DstPort)
|
|
|
|
return fmt.Sprintf("(%s %s:%d -> %s:%d)", proto, SrcIp, SrcPort, name, DstPort)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return fmt.Sprintf("%s %s %s:%d -> %s:%d", pinfo.ExePath, proto, SrcIp, SrcPort, name, DstPort)
|
|
|
|
return fmt.Sprintf("%s %s %s:%d -> %s:%d", pinfo.ExePath, proto, SrcIp, SrcPort, name, DstPort)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -412,8 +427,8 @@ func (fw *Firewall) filterPacket(pkt *nfqueue.NFQPacket) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_, dstip := getPacketIPAddrs(pkt)
|
|
|
|
_, dstip := getPacketIPAddrs(pkt)
|
|
|
|
/* _, dstp := getPacketPorts(pkt)
|
|
|
|
/* _, dstp := getPacketPorts(pkt)
|
|
|
|
fwo := matchAgainstOzRules(srcip, dstip, dstp)
|
|
|
|
fwo := eatchAgainstOzRules(srcip, dstip, dstp)
|
|
|
|
log.Notice("XXX: Attempting [2] to filter packet on rules -> ", fwo)
|
|
|
|
log.Notice("XXX: Attempting [2] to filter packet on rules -> ", fwo)
|
|
|
|
|
|
|
|
|
|
|
|
if fwo == OZ_FWRULE_WHITELIST {
|
|
|
|
if fwo == OZ_FWRULE_WHITELIST {
|
|
|
@ -440,8 +455,8 @@ func (fw *Firewall) filterPacket(pkt *nfqueue.NFQPacket) {
|
|
|
|
ppath = "[unknown]"
|
|
|
|
ppath = "[unknown]"
|
|
|
|
optstring = "[Connection could not be mapped]"
|
|
|
|
optstring = "[Connection could not be mapped]"
|
|
|
|
log.Warningf("No proc found for %s", printPacket(pkt, fw.dns.Lookup(dstip, pinfo.Pid), nil))
|
|
|
|
log.Warningf("No proc found for %s", printPacket(pkt, fw.dns.Lookup(dstip, pinfo.Pid), nil))
|
|
|
|
// pkt.Accept()
|
|
|
|
// pkt.Accept()
|
|
|
|
// return
|
|
|
|
// return
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
ppath = pinfo.ExePath
|
|
|
|
ppath = pinfo.ExePath
|
|
|
|
cf := strings.Fields(pinfo.CmdLine)
|
|
|
|
cf := strings.Fields(pinfo.CmdLine)
|
|
|
@ -455,13 +470,13 @@ func (fw *Firewall) filterPacket(pkt *nfqueue.NFQPacket) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Debugf("filterPacket [%s] %s", ppath, printPacket(pkt, fw.dns.Lookup(dstip, pinfo.Pid), nil))
|
|
|
|
log.Debugf("filterPacket [%s] %s", ppath, printPacket(pkt, fw.dns.Lookup(dstip, pinfo.Pid), nil))
|
|
|
|
/* if basicAllowPacket(pkt) {
|
|
|
|
/* if basicAllowPacket(pkt) {
|
|
|
|
pkt.Accept()
|
|
|
|
pkt.Accept()
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
policy := fw.PolicyForPath(ppath)
|
|
|
|
policy := fw.PolicyForPath(ppath)
|
|
|
|
//log.Notice("XXX: flunked basicallowpacket; policy = ", policy)
|
|
|
|
//log.Notice("XXX: flunked basicallowpacket; policy = ", policy)
|
|
|
|
policy.processPacket(pkt, pinfo, optstring)
|
|
|
|
policy.processPacket(pkt, pinfo, optstring)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -502,7 +517,7 @@ func getAllProcNetDataLocal() ([]string, error) {
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < len(OzInitPids); i++ {
|
|
|
|
for i := 0; i < len(OzInitPids); i++ {
|
|
|
|
fname := fmt.Sprintf("/proc/%d/net/tcp", OzInitPids[i])
|
|
|
|
fname := fmt.Sprintf("/proc/%d/net/tcp", OzInitPids[i])
|
|
|
|
//fmt.Println("XXX: opening: ", fname)
|
|
|
|
//fmt.Println("XXX: opening: ", fname)
|
|
|
|
bdata, err := readFileDirect(fname)
|
|
|
|
bdata, err := readFileDirect(fname)
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
@ -558,7 +573,7 @@ func LookupSandboxProc(srcip net.IP, srcp uint16, dstip net.IP, dstp uint16, pro
|
|
|
|
for i := 0; i < len(OzInitPids); i++ {
|
|
|
|
for i := 0; i < len(OzInitPids); i++ {
|
|
|
|
data := ""
|
|
|
|
data := ""
|
|
|
|
fname := fmt.Sprintf("/proc/%d/net/%s", OzInitPids[i].Pid, proto)
|
|
|
|
fname := fmt.Sprintf("/proc/%d/net/%s", OzInitPids[i].Pid, proto)
|
|
|
|
//fmt.Println("XXX: opening: ", fname)
|
|
|
|
//fmt.Println("XXX: opening: ", fname)
|
|
|
|
bdata, err := readFileDirect(fname)
|
|
|
|
bdata, err := readFileDirect(fname)
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
@ -594,7 +609,8 @@ func LookupSandboxProc(srcip net.IP, srcp uint16, dstip net.IP, dstp uint16, pro
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if res != nil {
|
|
|
|
if res != nil {
|
|
|
|
optstr = "Sandbox: " + OzInitPids[i].Name
|
|
|
|
// optstr = "Sandbox: " + OzInitPids[i].Name
|
|
|
|
|
|
|
|
res.Sandbox = OzInitPids[i].Name
|
|
|
|
res.ExePath = getRealRoot(res.ExePath, OzInitPids[i].Pid)
|
|
|
|
res.ExePath = getRealRoot(res.ExePath, OzInitPids[i].Pid)
|
|
|
|
break
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -657,7 +673,7 @@ func findProcessForPacket(pkt *nfqueue.NFQPacket, reverse bool, strictness int)
|
|
|
|
for i := 0; i < len(OzInitPids); i++ {
|
|
|
|
for i := 0; i < len(OzInitPids); i++ {
|
|
|
|
data := ""
|
|
|
|
data := ""
|
|
|
|
fname := fmt.Sprintf("/proc/%d/net/%s", OzInitPids[i].Pid, proto)
|
|
|
|
fname := fmt.Sprintf("/proc/%d/net/%s", OzInitPids[i].Pid, proto)
|
|
|
|
//fmt.Println("XXX: opening: ", fname)
|
|
|
|
//fmt.Println("XXX: opening: ", fname)
|
|
|
|
bdata, err := readFileDirect(fname)
|
|
|
|
bdata, err := readFileDirect(fname)
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
@ -741,7 +757,7 @@ func getPacketIPAddrs(pkt *nfqueue.NFQPacket) (net.IP, net.IP) {
|
|
|
|
|
|
|
|
|
|
|
|
if ipLayer == nil {
|
|
|
|
if ipLayer == nil {
|
|
|
|
if ipv4 {
|
|
|
|
if ipv4 {
|
|
|
|
return net.IP{0,0,0,0}, net.IP{0,0,0,0}
|
|
|
|
return net.IP{0, 0, 0, 0}, net.IP{0, 0, 0, 0}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return net.IP{}, net.IP{}
|
|
|
|
return net.IP{}, net.IP{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|