mirror of
https://github.com/safing/portmaster
synced 2025-09-04 11:39:29 +00:00
Start firewall/network/portmaster adaption
This commit is contained in:
parent
97a46d1e57
commit
99851166a0
11 changed files with 250 additions and 212 deletions
24
firewall/config.go
Normal file
24
firewall/config.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package firewall
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Safing/portbase/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
permanentVerdicts config.BoolOption
|
||||||
|
)
|
||||||
|
|
||||||
|
func prep() error {
|
||||||
|
err := config.Register(&config.Option{
|
||||||
|
Name: "Permanent Verdicts",
|
||||||
|
Key: "firewall/permanentVerdicts",
|
||||||
|
Description: "With permanent verdicts, control of a connection is fully handed back to the OS after the initial decision. This brings a great performance increase, but makes it impossible to change the decision of a link later on.",
|
||||||
|
ExpertiseLevel: config.ExpertiseLevelExpert,
|
||||||
|
OptType: config.OptTypeBool,
|
||||||
|
DefaultValue: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
configuredNameServers = config.Concurrent.GetAsBool("firewall/permanentVerdicts", true)
|
||||||
|
}
|
|
@ -8,17 +8,15 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/configuration"
|
"github.com/Safing/portbase/config"
|
||||||
"github.com/Safing/safing-core/firewall/inspection"
|
"github.com/Safing/portbase/log"
|
||||||
"github.com/Safing/safing-core/firewall/interception"
|
"github.com/Safing/portbase/modules"
|
||||||
"github.com/Safing/safing-core/log"
|
"github.com/Safing/portmaster/firewall/inspection"
|
||||||
"github.com/Safing/safing-core/modules"
|
"github.com/Safing/portmaster/firewall/interception"
|
||||||
"github.com/Safing/safing-core/network"
|
"github.com/Safing/portmaster/network"
|
||||||
"github.com/Safing/safing-core/network/packet"
|
"github.com/Safing/portmaster/network/packet"
|
||||||
"github.com/Safing/safing-core/port17/entry"
|
"github.com/Safing/portmaster/portmaster"
|
||||||
"github.com/Safing/safing-core/port17/mode"
|
"github.com/Safing/portmaster/process"
|
||||||
"github.com/Safing/safing-core/portmaster"
|
|
||||||
"github.com/Safing/safing-core/process"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -46,23 +44,25 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
modules.Register("firewall", prep, start, stop, "database", "nameserver")
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
func prep() (err error) {
|
||||||
|
|
||||||
_, localNet4, err = net.ParseCIDR("127.0.0.0/24")
|
_, localNet4, err = net.ParseCIDR("127.0.0.0/24")
|
||||||
// Yes, this would normally be 127.0.0.0/8
|
// Yes, this would normally be 127.0.0.0/8
|
||||||
// TODO: figure out any side effects
|
// TODO: figure out any side effects
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Criticalf("firewall: failed to parse cidr 127.0.0.0/24: %s", err)
|
return fmt.Errorf("firewall: failed to parse cidr 127.0.0.0/24: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, tunnelNet4, err = net.ParseCIDR("127.17.0.0/16")
|
_, tunnelNet4, err = net.ParseCIDR("127.17.0.0/16")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Criticalf("firewall: failed to parse cidr 127.17.0.0/16: %s", err)
|
return fmt.Errorf("firewall: failed to parse cidr 127.17.0.0/16: %s", err)
|
||||||
}
|
}
|
||||||
_, tunnelNet6, err = net.ParseCIDR("fd17::/64")
|
_, tunnelNet6, err = net.ParseCIDR("fd17::/64")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Criticalf("firewall: failed to parse cidr fd17::/64: %s", err)
|
return fmt.Errorf("firewall: failed to parse cidr fd17::/64: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var pA uint64
|
var pA uint64
|
||||||
|
@ -71,20 +71,19 @@ func init() {
|
||||||
packetsBlocked = &pB
|
packetsBlocked = &pB
|
||||||
var pD uint64
|
var pD uint64
|
||||||
packetsDropped = &pD
|
packetsDropped = &pD
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start() {
|
func start() {
|
||||||
firewallModule = modules.Register("Firewall", 128)
|
|
||||||
defer firewallModule.StopComplete()
|
|
||||||
|
|
||||||
// start interceptor
|
// start interceptor
|
||||||
go interception.Start()
|
interception.Start()
|
||||||
go statLogger()
|
|
||||||
|
|
||||||
|
go statLogger()
|
||||||
|
go run()
|
||||||
// go run()
|
// go run()
|
||||||
// go run()
|
// go run()
|
||||||
// go run()
|
// go run()
|
||||||
run()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePacket(pkt packet.Packet) {
|
func handlePacket(pkt packet.Packet) {
|
||||||
|
@ -189,19 +188,19 @@ func initialHandler(pkt packet.Packet, link *network.Link) {
|
||||||
logInitialVerdict(link)
|
logInitialVerdict(link)
|
||||||
|
|
||||||
// TODO: link this to real status
|
// TODO: link this to real status
|
||||||
port17Active := mode.Client()
|
// port17Active := mode.Client()
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case port17Active && link.Inspect:
|
// case port17Active && link.Inspect:
|
||||||
// tunnel link, but also inspect (after reroute)
|
// // tunnel link, but also inspect (after reroute)
|
||||||
link.Tunneled = true
|
// link.Tunneled = true
|
||||||
link.SetFirewallHandler(inspectThenVerdict)
|
// link.SetFirewallHandler(inspectThenVerdict)
|
||||||
verdict(pkt, link.Verdict)
|
// verdict(pkt, link.Verdict)
|
||||||
case port17Active:
|
// case port17Active:
|
||||||
// tunnel link, don't inspect
|
// // tunnel link, don't inspect
|
||||||
link.Tunneled = true
|
// link.Tunneled = true
|
||||||
link.StopFirewallHandler()
|
// link.StopFirewallHandler()
|
||||||
permanentVerdict(pkt, network.ACCEPT)
|
// permanentVerdict(pkt, network.ACCEPT)
|
||||||
case link.Inspect:
|
case link.Inspect:
|
||||||
link.SetFirewallHandler(inspectThenVerdict)
|
link.SetFirewallHandler(inspectThenVerdict)
|
||||||
inspectThenVerdict(pkt, link)
|
inspectThenVerdict(pkt, link)
|
||||||
|
@ -227,11 +226,7 @@ func inspectThenVerdict(pkt packet.Packet, link *network.Link) {
|
||||||
// we are done with inspecting
|
// we are done with inspecting
|
||||||
link.StopFirewallHandler()
|
link.StopFirewallHandler()
|
||||||
|
|
||||||
config.Changed()
|
link.VerdictPermanent = permanentVerdicts()
|
||||||
config.RLock()
|
|
||||||
link.VerdictPermanent = config.PermanentVerdicts
|
|
||||||
config.RUnlock()
|
|
||||||
|
|
||||||
if link.VerdictPermanent {
|
if link.VerdictPermanent {
|
||||||
link.Save()
|
link.Save()
|
||||||
permanentVerdict(pkt, link.Verdict)
|
permanentVerdict(pkt, link.Verdict)
|
||||||
|
@ -276,18 +271,18 @@ func verdict(pkt packet.Packet, action network.Verdict) {
|
||||||
pkt.Drop()
|
pkt.Drop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func tunnelHandler(pkt packet.Packet) {
|
// func tunnelHandler(pkt packet.Packet) {
|
||||||
tunnelInfo := portmaster.GetTunnelInfo(pkt.GetIPHeader().Dst)
|
// tunnelInfo := portmaster.GetTunnelInfo(pkt.GetIPHeader().Dst)
|
||||||
if tunnelInfo == nil {
|
// if tunnelInfo == nil {
|
||||||
pkt.Block()
|
// pkt.Block()
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
entry.CreateTunnel(pkt, tunnelInfo.Domain, tunnelInfo.RRCache.ExportAllARecords())
|
// entry.CreateTunnel(pkt, tunnelInfo.Domain, tunnelInfo.RRCache.ExportAllARecords())
|
||||||
log.Tracef("firewall: rerouting %s to tunnel entry point", pkt)
|
// log.Tracef("firewall: rerouting %s to tunnel entry point", pkt)
|
||||||
pkt.RerouteToTunnel()
|
// pkt.RerouteToTunnel()
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
func logInitialVerdict(link *network.Link) {
|
func logInitialVerdict(link *network.Link) {
|
||||||
// switch link.Verdict {
|
// switch link.Verdict {
|
||||||
|
@ -312,25 +307,26 @@ func logChangedVerdict(link *network.Link) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func run() {
|
func run() {
|
||||||
|
|
||||||
packetProcessingLoop:
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-firewallModule.Stop:
|
case <-modules.ShuttingDown():
|
||||||
break packetProcessingLoop
|
return
|
||||||
case pkt := <-interception.Packets:
|
case pkt := <-interception.Packets:
|
||||||
handlePacket(pkt)
|
handlePacket(pkt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func statLogger() {
|
func statLogger() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(10 * time.Second)
|
select {
|
||||||
log.Tracef("firewall: packets accepted %d, blocked %d, dropped %d", atomic.LoadUint64(packetsAccepted), atomic.LoadUint64(packetsBlocked), atomic.LoadUint64(packetsDropped))
|
case <-modules.ShuttingDown():
|
||||||
atomic.StoreUint64(packetsAccepted, 0)
|
return
|
||||||
atomic.StoreUint64(packetsBlocked, 0)
|
case <-time.After(10 * time.Second):
|
||||||
atomic.StoreUint64(packetsDropped, 0)
|
log.Tracef("firewall: packets accepted %d, blocked %d, dropped %d", atomic.LoadUint64(packetsAccepted), atomic.LoadUint64(packetsBlocked), atomic.LoadUint64(packetsDropped))
|
||||||
|
atomic.StoreUint64(packetsAccepted, 0)
|
||||||
|
atomic.StoreUint64(packetsBlocked, 0)
|
||||||
|
atomic.StoreUint64(packetsDropped, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
package inspection
|
package inspection
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Safing/safing-core/network"
|
|
||||||
"github.com/Safing/safing-core/network/packet"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Safing/portmaster/network"
|
||||||
|
"github.com/Safing/portmaster/network/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
package interception
|
package interception
|
||||||
|
|
||||||
import "github.com/Safing/safing-core/network/packet"
|
import "github.com/Safing/portmaster/network/packet"
|
||||||
|
|
||||||
var Packets chan packet.Packet
|
var (
|
||||||
|
|
||||||
func init() {
|
|
||||||
Packets = make(chan packet.Packet, 1000)
|
Packets = make(chan packet.Packet, 1000)
|
||||||
}
|
)
|
||||||
|
|
|
@ -5,27 +5,33 @@
|
||||||
package interception
|
package interception
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
"github.com/coreos/go-iptables/iptables"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/firewall/interception/nfqueue"
|
"github.com/Safing/portmaster/firewall/interception/nfqueue"
|
||||||
"github.com/Safing/safing-core/log"
|
|
||||||
"github.com/Safing/safing-core/modules"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// iptables -A OUTPUT -p icmp -j", "NFQUEUE", "--queue-num", "1", "--queue-bypass
|
// iptables -A OUTPUT -p icmp -j", "NFQUEUE", "--queue-num", "1", "--queue-bypass
|
||||||
|
|
||||||
var nfqueueModule *modules.Module
|
var (
|
||||||
|
v4chains []string
|
||||||
|
v4rules []string
|
||||||
|
v4once []string
|
||||||
|
|
||||||
var v4chains []string
|
v6chains []string
|
||||||
var v4rules []string
|
v6rules []string
|
||||||
var v4once []string
|
v6once []string
|
||||||
|
|
||||||
var v6chains []string
|
out4Queue *nfqueue.NFQueue
|
||||||
var v6rules []string
|
in4Queue *nfqueue.NFQueue
|
||||||
var v6once []string
|
out6Queue *nfqueue.NFQueue
|
||||||
|
in6Queue *nfqueue.NFQueue
|
||||||
|
|
||||||
|
shutdownSignal = make(chan struct{})
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
|
@ -238,70 +244,84 @@ func deactivateNfqueueFirewall() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start() {
|
// Start starts the nfqueue interception.
|
||||||
|
func Start() (err error) {
|
||||||
|
|
||||||
nfqueueModule = modules.Register("Firewall:Interception:Nfqueue", 192)
|
err = activateNfqueueFirewall()
|
||||||
|
if err != nil {
|
||||||
if err := activateNfqueueFirewall(); err != nil {
|
Stop()
|
||||||
log.Criticalf("could not activate firewall for nfqueue: %q", err)
|
return fmt.Errorf("could not initialize nfqueue: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
out4Queue := nfqueue.NewNFQueue(17040)
|
out4Queue, err = nfqueue.NewNFQueue(17040)
|
||||||
in4Queue := nfqueue.NewNFQueue(17140)
|
if err != nil {
|
||||||
out6Queue := nfqueue.NewNFQueue(17060)
|
Stop()
|
||||||
in6Queue := nfqueue.NewNFQueue(17160)
|
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||||
|
}
|
||||||
|
in4Queue, err = nfqueue.NewNFQueue(17140)
|
||||||
|
if err != nil {
|
||||||
|
Stop()
|
||||||
|
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||||
|
}
|
||||||
|
out6Queue, err = nfqueue.NewNFQueue(17060)
|
||||||
|
if err != nil {
|
||||||
|
Stop()
|
||||||
|
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||||
|
}
|
||||||
|
in6Queue, err = nfqueue.NewNFQueue(17160)
|
||||||
|
if err != nil {
|
||||||
|
Stop()
|
||||||
|
return fmt.Errorf("interception: failed to create nfqueue(IPv4, in): %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
out4Channel := out4Queue.Process()
|
go handleInterception()
|
||||||
// if err != nil {
|
return nil
|
||||||
// log.Criticalf("could not open nfqueue out4")
|
}
|
||||||
// } else {
|
|
||||||
defer out4Queue.Destroy()
|
|
||||||
// }
|
|
||||||
in4Channel := in4Queue.Process()
|
|
||||||
// if err != nil {
|
|
||||||
// log.Criticalf("could not open nfqueue in4")
|
|
||||||
// } else {
|
|
||||||
defer in4Queue.Destroy()
|
|
||||||
// }
|
|
||||||
out6Channel := out6Queue.Process()
|
|
||||||
// if err != nil {
|
|
||||||
// log.Criticalf("could not open nfqueue out6")
|
|
||||||
// } else {
|
|
||||||
defer out6Queue.Destroy()
|
|
||||||
// }
|
|
||||||
in6Channel := in6Queue.Process()
|
|
||||||
// if err != nil {
|
|
||||||
// log.Criticalf("could not open nfqueue in6")
|
|
||||||
// } else {
|
|
||||||
defer in6Queue.Destroy()
|
|
||||||
// }
|
|
||||||
|
|
||||||
packetInterceptionLoop:
|
// Stop stops the nfqueue interception.
|
||||||
|
func Stop() error {
|
||||||
|
defer close(shutdownSignal)
|
||||||
|
|
||||||
|
if out4Queue != nil {
|
||||||
|
out4Queue.Destroy()
|
||||||
|
}
|
||||||
|
if in4Queue != nil {
|
||||||
|
in4Queue.Destroy()
|
||||||
|
}
|
||||||
|
if out6Queue != nil {
|
||||||
|
out6Queue.Destroy()
|
||||||
|
}
|
||||||
|
if in6Queue != nil {
|
||||||
|
in6Queue.Destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
err := deactivateNfqueueFirewall()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("interception: error while deactivating nfqueue: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleInterception() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-nfqueueModule.Stop:
|
case <-shutdownSignal:
|
||||||
break packetInterceptionLoop
|
return
|
||||||
case pkt := <-out4Channel:
|
case pkt := <-out4Queue.Packets:
|
||||||
pkt.SetOutbound()
|
pkt.SetOutbound()
|
||||||
Packets <- pkt
|
Packets <- pkt
|
||||||
case pkt := <-in4Channel:
|
case pkt := <-in4Queue.Packets:
|
||||||
pkt.SetInbound()
|
pkt.SetInbound()
|
||||||
Packets <- pkt
|
Packets <- pkt
|
||||||
case pkt := <-out6Channel:
|
case pkt := <-out6Queue.Packets:
|
||||||
pkt.SetOutbound()
|
pkt.SetOutbound()
|
||||||
Packets <- pkt
|
Packets <- pkt
|
||||||
case pkt := <-in6Channel:
|
case pkt := <-in6Queue.Packets:
|
||||||
pkt.SetInbound()
|
pkt.SetInbound()
|
||||||
Packets <- pkt
|
Packets <- pkt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := deactivateNfqueueFirewall(); err != nil {
|
|
||||||
log.Criticalf("could not deactivate firewall for nfqueue: %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
nfqueueModule.StopComplete()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringInSlice(slice []string, value string) bool {
|
func stringInSlice(slice []string, value string) bool {
|
||||||
|
|
|
@ -2,45 +2,48 @@
|
||||||
|
|
||||||
package nfqueue
|
package nfqueue
|
||||||
|
|
||||||
import (
|
// suspended for now
|
||||||
"github.com/Safing/safing-core/network/packet"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type multiQueue struct {
|
// import (
|
||||||
qs []*nfQueue
|
// "sync"
|
||||||
}
|
//
|
||||||
|
// "github.com/Safing/portmaster/network/packet"
|
||||||
func NewMultiQueue(min, max uint16) (mq *multiQueue) {
|
// )
|
||||||
mq = &multiQueue{make([]*nfQueue, 0, max-min)}
|
//
|
||||||
for i := min; i < max; i++ {
|
// type multiQueue struct {
|
||||||
mq.qs = append(mq.qs, NewNFQueue(i))
|
// qs []*NFQueue
|
||||||
}
|
// }
|
||||||
return mq
|
//
|
||||||
}
|
// func NewMultiQueue(min, max uint16) (mq *multiQueue) {
|
||||||
|
// mq = &multiQueue{make([]*NFQueue, 0, max-min)}
|
||||||
func (mq *multiQueue) Process() <-chan packet.Packet {
|
// for i := min; i < max; i++ {
|
||||||
var (
|
// mq.qs = append(mq.qs, NewNFQueue(i))
|
||||||
wg sync.WaitGroup
|
// }
|
||||||
out = make(chan packet.Packet, len(mq.qs))
|
// return mq
|
||||||
)
|
// }
|
||||||
for _, q := range mq.qs {
|
//
|
||||||
wg.Add(1)
|
// func (mq *multiQueue) Process() <-chan packet.Packet {
|
||||||
go func(ch <-chan packet.Packet) {
|
// var (
|
||||||
for pkt := range ch {
|
// wg sync.WaitGroup
|
||||||
out <- pkt
|
// out = make(chan packet.Packet, len(mq.qs))
|
||||||
}
|
// )
|
||||||
wg.Done()
|
// for _, q := range mq.qs {
|
||||||
}(q.Process())
|
// wg.Add(1)
|
||||||
}
|
// go func(ch <-chan packet.Packet) {
|
||||||
go func() {
|
// for pkt := range ch {
|
||||||
wg.Wait()
|
// out <- pkt
|
||||||
close(out)
|
// }
|
||||||
}()
|
// wg.Done()
|
||||||
return out
|
// }(q.Process())
|
||||||
}
|
// }
|
||||||
func (mq *multiQueue) Destroy() {
|
// go func() {
|
||||||
for _, q := range mq.qs {
|
// wg.Wait()
|
||||||
q.Destroy()
|
// close(out)
|
||||||
}
|
// }()
|
||||||
}
|
// return out
|
||||||
|
// }
|
||||||
|
// func (mq *multiQueue) Destroy() {
|
||||||
|
// for _, q := range mq.qs {
|
||||||
|
// q.Destroy()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
@ -17,17 +17,19 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/network/packet"
|
"github.com/Safing/portmaster/network/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
var queues map[uint16]*nfQueue
|
var queues map[uint16]*NFQueue
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
queues = make(map[uint16]*nfQueue)
|
queues = make(map[uint16]*NFQueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
type nfQueue struct {
|
type NFQueue struct {
|
||||||
DefaultVerdict uint32
|
DefaultVerdict uint32
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
qid uint16
|
qid uint16
|
||||||
|
@ -38,83 +40,77 @@ type nfQueue struct {
|
||||||
fd int
|
fd int
|
||||||
lk sync.Mutex
|
lk sync.Mutex
|
||||||
|
|
||||||
pktch chan packet.Packet
|
Packets chan packet.Packet
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNFQueue(qid uint16) (nfq *nfQueue) {
|
func NewNFQueue(qid uint16) (nfq *NFQueue, err error) {
|
||||||
if os.Geteuid() != 0 {
|
if os.Geteuid() != 0 {
|
||||||
panic("Must be ran by root.")
|
return nil, errors.New("must be root to intercept packets")
|
||||||
}
|
}
|
||||||
nfq = &nfQueue{DefaultVerdict: NFQ_ACCEPT, Timeout: 100 * time.Millisecond, qid: qid, qidptr: &qid}
|
nfq = &NFQueue{DefaultVerdict: NFQ_ACCEPT, Timeout: 100 * time.Millisecond, qid: qid, qidptr: &qid}
|
||||||
queues[nfq.qid] = nfq
|
queues[nfq.qid] = nfq
|
||||||
return nfq
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
err = nfq.init()
|
||||||
This returns a channel that will recieve packets,
|
if err != nil {
|
||||||
the user then must call pkt.Accept() or pkt.Drop()
|
return nil, err
|
||||||
*/
|
|
||||||
func (this *nfQueue) Process() <-chan packet.Packet {
|
|
||||||
if this.h != nil {
|
|
||||||
return this.pktch
|
|
||||||
}
|
}
|
||||||
this.init()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
C.loop_for_packets(this.h)
|
C.loop_for_packets(nfq.h)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return this.pktch
|
return nfq, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *nfQueue) init() {
|
func (this *NFQueue) init() error {
|
||||||
var err error
|
var err error
|
||||||
if this.h, err = C.nfq_open(); err != nil || this.h == nil {
|
if this.h, err = C.nfq_open(); err != nil || this.h == nil {
|
||||||
panic(err)
|
fmt.Errorf("could not open nfqueue: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//if this.qh, err = C.nfq_create_queue(this.h, qid, C.get_cb(), unsafe.Pointer(nfq)); err != nil || this.qh == nil {
|
//if this.qh, err = C.nfq_create_queue(this.h, qid, C.get_cb(), unsafe.Pointer(nfq)); err != nil || this.qh == nil {
|
||||||
|
|
||||||
this.pktch = make(chan packet.Packet, 1)
|
this.Packets = make(chan packet.Packet, 1)
|
||||||
|
|
||||||
if C.nfq_unbind_pf(this.h, C.AF_INET) < 0 {
|
if C.nfq_unbind_pf(this.h, C.AF_INET) < 0 {
|
||||||
this.Destroy()
|
this.Destroy()
|
||||||
panic("nfq_unbind_pf(AF_INET) failed, are you running root?.")
|
return errors.New("nfq_unbind_pf(AF_INET) failed, are you root?")
|
||||||
}
|
}
|
||||||
if C.nfq_unbind_pf(this.h, C.AF_INET6) < 0 {
|
if C.nfq_unbind_pf(this.h, C.AF_INET6) < 0 {
|
||||||
this.Destroy()
|
this.Destroy()
|
||||||
panic("nfq_unbind_pf(AF_INET6) failed.")
|
return errors.New("nfq_unbind_pf(AF_INET6) failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if C.nfq_bind_pf(this.h, C.AF_INET) < 0 {
|
if C.nfq_bind_pf(this.h, C.AF_INET) < 0 {
|
||||||
this.Destroy()
|
this.Destroy()
|
||||||
panic("nfq_bind_pf(AF_INET) failed.")
|
return errors.New("nfq_bind_pf(AF_INET) failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if C.nfq_bind_pf(this.h, C.AF_INET6) < 0 {
|
if C.nfq_bind_pf(this.h, C.AF_INET6) < 0 {
|
||||||
this.Destroy()
|
this.Destroy()
|
||||||
panic("nfq_bind_pf(AF_INET6) failed.")
|
return errors.New("nfq_bind_pf(AF_INET6) failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if this.qh, err = C.create_queue(this.h, C.uint16_t(this.qid)); err != nil || this.qh == nil {
|
if this.qh, err = C.create_queue(this.h, C.uint16_t(this.qid)); err != nil || this.qh == nil {
|
||||||
C.nfq_close(this.h)
|
C.nfq_close(this.h)
|
||||||
panic(err)
|
return fmt.Errorf("could not create queue: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fd = int(C.nfq_fd(this.h))
|
this.fd = int(C.nfq_fd(this.h))
|
||||||
|
|
||||||
if C.nfq_set_mode(this.qh, C.NFQNL_COPY_PACKET, 0xffff) < 0 {
|
if C.nfq_set_mode(this.qh, C.NFQNL_COPY_PACKET, 0xffff) < 0 {
|
||||||
this.Destroy()
|
this.Destroy()
|
||||||
panic("nfq_set_mode(NFQNL_COPY_PACKET) failed.")
|
return errors.New("nfq_set_mode(NFQNL_COPY_PACKET) failed")
|
||||||
}
|
}
|
||||||
if C.nfq_set_queue_maxlen(this.qh, 1024*8) < 0 {
|
if C.nfq_set_queue_maxlen(this.qh, 1024*8) < 0 {
|
||||||
this.Destroy()
|
this.Destroy()
|
||||||
panic("nfq_set_queue_maxlen(1024 * 8) failed.")
|
return errors.New("nfq_set_queue_maxlen(1024 * 8) failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *nfQueue) Destroy() {
|
func (this *NFQueue) Destroy() {
|
||||||
this.lk.Lock()
|
this.lk.Lock()
|
||||||
defer this.lk.Unlock()
|
defer this.lk.Unlock()
|
||||||
|
|
||||||
|
@ -131,12 +127,12 @@ func (this *nfQueue) Destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: don't close, we're exiting anyway
|
// TODO: don't close, we're exiting anyway
|
||||||
// if this.pktch != nil {
|
// if this.Packets != nil {
|
||||||
// close(this.pktch)
|
// close(this.Packets)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *nfQueue) Valid() bool {
|
func (this *NFQueue) Valid() bool {
|
||||||
return this.h != nil && this.qh != nil
|
return this.h != nil && this.qh != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +144,7 @@ func go_nfq_callback(id uint32, hwproto uint16, hook uint8, mark *uint32,
|
||||||
qidptr := (*uint16)(data)
|
qidptr := (*uint16)(data)
|
||||||
qid := uint16(*qidptr)
|
qid := uint16(*qidptr)
|
||||||
|
|
||||||
// nfq := (*nfQueue)(nfqptr)
|
// nfq := (*NFQueue)(nfqptr)
|
||||||
new_version := version
|
new_version := version
|
||||||
ipver := packet.IPVersion(new_version)
|
ipver := packet.IPVersion(new_version)
|
||||||
ipsz := C.int(ipver.ByteSize())
|
ipsz := C.int(ipver.ByteSize())
|
||||||
|
@ -187,7 +183,7 @@ func go_nfq_callback(id uint32, hwproto uint16, hook uint8, mark *uint32,
|
||||||
|
|
||||||
// fmt.Printf("%s queuing packet\n", time.Now().Format("060102 15:04:05.000"))
|
// fmt.Printf("%s queuing packet\n", time.Now().Format("060102 15:04:05.000"))
|
||||||
// BUG: "panic: send on closed channel" when shutting down
|
// BUG: "panic: send on closed channel" when shutting down
|
||||||
queues[qid].pktch <- &pkt
|
queues[qid].Packets <- &pkt
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case v = <-pkt.verdict:
|
case v = <-pkt.verdict:
|
||||||
|
|
|
@ -5,7 +5,7 @@ package nfqueue
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/network/packet"
|
"github.com/Safing/portmaster/network/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/database"
|
"github.com/Safing/portbase/database"
|
||||||
"github.com/Safing/safing-core/intel"
|
"github.com/Safing/portmaster/intel"
|
||||||
"github.com/Safing/safing-core/network/packet"
|
"github.com/Safing/portmaster/network/packet"
|
||||||
"github.com/Safing/safing-core/process"
|
"github.com/Safing/portmaster/process"
|
||||||
|
|
||||||
datastore "github.com/ipfs/go-datastore"
|
datastore "github.com/ipfs/go-datastore"
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
|
|
||||||
datastore "github.com/ipfs/go-datastore"
|
datastore "github.com/ipfs/go-datastore"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/database"
|
"github.com/Safing/portbase/database"
|
||||||
"github.com/Safing/safing-core/log"
|
"github.com/Safing/portbase/log"
|
||||||
"github.com/Safing/safing-core/network/packet"
|
"github.com/Safing/portmaster/network/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FirewallHandler func(pkt packet.Packet, link *Link)
|
type FirewallHandler func(pkt packet.Packet, link *Link)
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Safing/safing-core/crypto/random"
|
"github.com/Safing/portbase/crypto/random"
|
||||||
"github.com/Safing/safing-core/intel"
|
"github.com/Safing/portmaster/intel"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue