Go binary writing

This commit is contained in:
DomySh
2022-07-14 01:22:23 +02:00
parent 3de95f1dcc
commit 52e016ef33
3 changed files with 117 additions and 39 deletions

1
.gitignore vendored
View File

@@ -12,6 +12,7 @@
/backend/db/firegex.db /backend/db/firegex.db
/backend/db/firegex.db-journal /backend/db/firegex.db-journal
/backend/nfqueue/main
docker-compose.yml docker-compose.yml
# misc # misc

Binary file not shown.

View File

@@ -12,21 +12,37 @@ import (
"github.com/DomySh/go-netfilter-queue" "github.com/DomySh/go-netfilter-queue"
"github.com/Jemmic/go-pcre2" "github.com/Jemmic/go-pcre2"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
) )
const QUEUE_BASE_NUM = 1000 const QUEUE_BASE_NUM = 1000
const MAX_PACKET_IN_QUEUE = 100 const MAX_PACKET_IN_QUEUE = 100
var FILTER_TABLE *regex_filters = &regex_filters{} type regex_pair struct {
regex string
type regex_filters struct { matcher *pcre2.Matcher
input_whitelist []*pcre2.Matcher
input_blacklist []*pcre2.Matcher
output_whitelist []*pcre2.Matcher
output_blacklist []*pcre2.Matcher
} }
func (self regex_filters) add(raw_regex string) { type regex_filters struct {
input_whitelist []regex_pair
input_blacklist []regex_pair
output_whitelist []regex_pair
output_blacklist []regex_pair
regexes []*pcre2.Regexp
}
func NewRegexFilter() *regex_filters {
res := new(regex_filters)
res.input_blacklist = make([]regex_pair, 0)
res.input_whitelist = make([]regex_pair, 0)
res.output_blacklist = make([]regex_pair, 0)
res.output_whitelist = make([]regex_pair, 0)
res.regexes = make([]*pcre2.Regexp, 0)
return res
}
func (self *regex_filters) add(raw_regex string) {
filter_type := strings.ToLower(raw_regex[0:2]) filter_type := strings.ToLower(raw_regex[0:2])
decoded_regex, err := hex.DecodeString(raw_regex[2:]) decoded_regex, err := hex.DecodeString(raw_regex[2:])
@@ -40,41 +56,46 @@ func (self regex_filters) add(raw_regex string) {
log.Printf("[add] Unable to compile regex '%s': %s", string(decoded_regex), err) log.Printf("[add] Unable to compile regex '%s': %s", string(decoded_regex), err)
return return
} }
self.regexes = append(self.regexes, regex)
if filter_type[0] == 'i' { if filter_type[0] == 'i' {
if filter_type[1] == '0' { if filter_type[1] == '1' {
self.input_whitelist = append(self.input_whitelist, regex.NewMatcher()) self.input_whitelist = append(self.input_whitelist, regex_pair{raw_regex, regex.NewMatcher()})
} else { } else {
self.input_blacklist = append(self.input_blacklist, regex.NewMatcher()) self.input_blacklist = append(self.input_blacklist, regex_pair{raw_regex, regex.NewMatcher()})
} }
} else { } else {
if filter_type[1] == '0' { if filter_type[1] == '1' {
self.output_whitelist = append(self.output_whitelist, regex.NewMatcher()) self.output_whitelist = append(self.output_whitelist, regex_pair{raw_regex, regex.NewMatcher()})
} else { } else {
self.output_blacklist = append(self.output_blacklist, regex.NewMatcher()) self.output_blacklist = append(self.output_blacklist, regex_pair{raw_regex, regex.NewMatcher()})
} }
} }
} }
func (self regex_filters) check(data []byte, is_input bool) bool { func (self *regex_filters) check(data []byte, is_input bool) bool {
if is_input { if is_input {
for _, matcher := range self.input_blacklist { for _, rgx := range self.input_blacklist {
if matcher.Match(data, 0) { if rgx.matcher.Match(data, 0) {
fmt.Printf("BLOCKED %s\n", rgx.regex)
return false return false
} }
} }
for _, matcher := range self.input_whitelist { for _, rgx := range self.input_whitelist {
if !matcher.Match(data, 0) { if !rgx.matcher.Match(data, 0) {
fmt.Printf("BLOCKED %s\n", rgx.regex)
return false return false
} }
} }
} else { } else {
for _, matcher := range self.output_blacklist { for _, rgx := range self.output_blacklist {
if matcher.Match(data, 0) { if rgx.matcher.Match(data, 0) {
fmt.Printf("BLOCKED %s\n", rgx.regex)
return false return false
} }
} }
for _, matcher := range self.output_whitelist { for _, rgx := range self.output_whitelist {
if !matcher.Match(data, 0) { if !rgx.matcher.Match(data, 0) {
fmt.Printf("BLOCKED %s\n", rgx.regex)
return false return false
} }
} }
@@ -82,18 +103,64 @@ func (self regex_filters) check(data []byte, is_input bool) bool {
return true return true
} }
func handle_packets(packets <-chan netfilter.NFPacket, is_input bool) { func (self *regex_filters) clear() {
for _, rgx := range self.input_whitelist {
rgx.matcher.Free()
}
for _, rgx := range self.input_blacklist {
rgx.matcher.Free()
}
for _, rgx := range self.output_whitelist {
rgx.matcher.Free()
}
for _, rgx := range self.output_blacklist {
rgx.matcher.Free()
}
for _, regex := range self.regexes {
regex.Free()
}
}
func handle_packets(packets <-chan netfilter.NFPacket, filter_table_channel chan regex_filters, is_input bool) {
filter_table := regex_filters{}
for true { for true {
filter := FILTER_TABLE filter := filter_table
p := <-packets select {
log.Printf("Packet received: %s input: %t", p.Packet.TransportLayer().LayerPayload(), is_input) case ft := <-filter_table_channel:
if filter.check(p.Packet.TransportLayer().LayerPayload(), is_input) { {
filter_table = ft
}
case p := <-packets:
{
transport_layer := p.Packet.TransportLayer()
data := transport_layer.LayerPayload()
if len(data) > 0 {
if filter.check(data, is_input) {
p.SetVerdict(netfilter.NF_ACCEPT) p.SetVerdict(netfilter.NF_ACCEPT)
} else { } else {
log.Printf("Refused packet: %s", p.Packet.TransportLayer().LayerPayload()) if transport_layer.LayerType() == layers.LayerTypeTCP {
*p.Packet.ApplicationLayer().(*gopacket.Payload) = []byte{}
transport_layer.(*layers.TCP).Payload = []byte{}
transport_layer.(*layers.TCP).FIN = true
transport_layer.(*layers.TCP).SYN = false
transport_layer.(*layers.TCP).RST = false
transport_layer.(*layers.TCP).ACK = true
transport_layer.(*layers.TCP).SetNetworkLayerForChecksum(p.Packet.NetworkLayer())
buffer := gopacket.NewSerializeBuffer()
options := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}
if err := gopacket.SerializePacket(buffer, options, p.Packet); err != nil {
p.SetVerdict(netfilter.NF_DROP) p.SetVerdict(netfilter.NF_DROP)
} }
p.SetVerdictWithPacket(netfilter.NF_ACCEPT, buffer.Bytes())
} else {
p.SetVerdict(netfilter.NF_DROP)
}
}
} else {
p.SetVerdict(netfilter.NF_ACCEPT)
}
}
}
} }
} }
@@ -144,24 +211,29 @@ func main() {
log.Fatalf("[main] Invalid number of queues: %s", err) log.Fatalf("[main] Invalid number of queues: %s", err)
} }
} }
var filter_channels []chan regex_filters
// Start the queue list // Start the queue list
queue_list, starts_input, end_input := create_queue_seq(number_of_queues) queue_list, starts_input, end_input := create_queue_seq(number_of_queues)
for _, queue := range queue_list { for _, queue := range queue_list {
defer queue.Close() defer queue.Close()
go handle_packets(queue.GetPackets(), true) ch := make(chan regex_filters)
filter_channels = append(filter_channels, ch)
go handle_packets(queue.GetPackets(), ch, true)
} }
queue_list, starts_output, end_output := create_queue_seq(number_of_queues) queue_list, starts_output, end_output := create_queue_seq(number_of_queues)
for _, queue := range queue_list { for _, queue := range queue_list {
defer queue.Close() defer queue.Close()
go handle_packets(queue.GetPackets(), false) ch := make(chan regex_filters)
filter_channels = append(filter_channels, ch)
go handle_packets(queue.GetPackets(), ch, false)
} }
fmt.Println("QUEUE INPUT", starts_input, end_input, "OUTPUT", starts_output, end_output) fmt.Println("QUEUE INPUT", starts_input, end_input, "OUTPUT", starts_output, end_output)
//Reading for new configuration //Reading for new configuration
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
old_filter_table := NewRegexFilter()
for true { for true {
text, err := reader.ReadString('\n') text, err := reader.ReadString('\n')
log.Printf("[main] Regex rule updating...") log.Printf("[main] Regex rule updating...")
@@ -171,7 +243,7 @@ func main() {
text = strings.Trim(text, "\n") text = strings.Trim(text, "\n")
regexes := strings.Split(text, " ") regexes := strings.Split(text, " ")
new_filters := regex_filters{} new_filters := NewRegexFilter()
for _, regex := range regexes { for _, regex := range regexes {
regex = strings.Trim(regex, " ") regex = strings.Trim(regex, " ")
if len(regex) < 2 { if len(regex) < 2 {
@@ -179,7 +251,12 @@ func main() {
} }
new_filters.add(regex) new_filters.add(regex)
} }
FILTER_TABLE = &new_filters for _, ch := range filter_channels {
ch <- *new_filters
}
old_filter_table.clear()
old_filter_table = new_filters
log.Printf("[main] Regex filter rules updated!") log.Printf("[main] Regex filter rules updated!")
} }
} }