Skip to content

Commit

Permalink
basic filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
superstes committed Sep 25, 2023
1 parent d99e0e0 commit cff176c
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 25 deletions.
1 change: 1 addition & 0 deletions config_example.yml
Expand Up @@ -49,3 +49,4 @@ rules:
port: 443
protoL4: 'tcp'
action: 'accept'

Check failure on line 52 in config_example.yml

View workflow job for this annotation

GitHub Actions / build (3.1)

52:1 [trailing-spaces] trailing spaces
16 changes: 8 additions & 8 deletions lib/cnf/cnf_file/rules_parse.go
Expand Up @@ -42,7 +42,7 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.SrcNet[i2]) {
if negate(value) {
rule.Match.SrcNetN = append(rule.Match.SrcNetN, matchNet(value))
} else {
rule.Match.SrcNet = append(rule.Match.SrcNet, matchNet(value))
Expand All @@ -67,15 +67,15 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.DestNet[i2]) {
if negate(value) {
rule.Match.DestNetN = append(rule.Match.DestNetN, matchNet(value))
} else {
rule.Match.DestNet = append(rule.Match.DestNet, matchNet(value))
}
}
}

// source ports
// source ports; todo: support for port ranges
if len(ruleRaw.Match.SrcPort) > 0 {
rule.Match.SrcPort = []uint16{}
rule.Match.SrcPortN = []uint16{}
Expand All @@ -92,7 +92,7 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.SrcPort[i2]) {
if negate(value) {
rule.Match.SrcPortN = append(rule.Match.SrcPortN, matchPort(value))
} else {
rule.Match.SrcPort = append(rule.Match.SrcPort, matchPort(value))
Expand All @@ -117,7 +117,7 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.DestPort[i2]) {
if negate(value) {
rule.Match.DestPortN = append(rule.Match.DestPortN, matchPort(value))
} else {
rule.Match.DestPort = append(rule.Match.DestPort, matchPort(value))
Expand All @@ -142,7 +142,7 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.ProtoL3[i2]) {
if negate(value) {
rule.Match.ProtoL3N = append(rule.Match.ProtoL3N, matchProtoL3(value))
} else {
rule.Match.ProtoL3 = append(rule.Match.ProtoL3, matchProtoL3(value))
Expand All @@ -167,7 +167,7 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.ProtoL4[i2]) {
if negate(value) {
rule.Match.ProtoL4N = append(rule.Match.ProtoL4N, matchProtoL4(value))
} else {
rule.Match.ProtoL4 = append(rule.Match.ProtoL4, matchProtoL4(value))
Expand All @@ -192,7 +192,7 @@ func ParseRules(rawRules []cnf.RuleRaw) (rules []cnf.Rule) {
}
}
} else {
if negate(ruleRaw.Match.ProtoL5[i2]) {
if negate(value) {
rule.Match.ProtoL5N = append(rule.Match.ProtoL5N, matchProtoL5(value))
} else {
rule.Match.ProtoL5 = append(rule.Match.ProtoL5, matchProtoL5(value))
Expand Down
2 changes: 1 addition & 1 deletion lib/cnf/rules.go
Expand Up @@ -42,5 +42,5 @@ type Match struct {
ProtoL4N []meta.Proto
ProtoL5 []meta.Proto
ProtoL5N []meta.Proto
Domains YamlStringArray
Domains []string
}
166 changes: 162 additions & 4 deletions lib/proc/filter/main.go
@@ -1,20 +1,178 @@
package filter

import (
"fmt"
"net"

"github.com/superstes/calamary/cnf"
"github.com/superstes/calamary/log"
"github.com/superstes/calamary/proc/meta"
"github.com/superstes/calamary/proc/parse"
)

// http://www.squid-cache.org/Doc/config/acl/

func Filter(pkg parse.ParsedPackage) bool {
// just test filter
_, netip, _ := net.ParseCIDR("135.181.170.219/32")
if netip.Contains(pkg.L3.DestIP) && pkg.L4.DestPort == 443 {
return true
for rid := range *cnf.RULES {
rule := (*cnf.RULES)[rid]

// protocols layer 3
if rule.Match.ProtoL3 != nil && len(rule.Match.ProtoL3) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("Proto L3: %v vs %v", rule.Match.ProtoL3, pkg.L3.Proto))
if !anyProtoMatch(rule.Match.ProtoL3, pkg.L3.Proto) {
continue
}
}
if rule.Match.ProtoL3N != nil && len(rule.Match.ProtoL3N) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("!Proto L3: %v vs %v", rule.Match.ProtoL3N, pkg.L3.Proto))
if anyProtoMatch(rule.Match.ProtoL3N, pkg.L3.Proto) {
continue
}
}

// protocols layer 4
if rule.Match.ProtoL4 != nil && len(rule.Match.ProtoL4) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("Proto L4: %v vs %v", rule.Match.ProtoL4, pkg.L3.L4Proto))
if !anyProtoMatch(rule.Match.ProtoL4, pkg.L3.L4Proto) {
continue
}
}
if rule.Match.ProtoL4N != nil && len(rule.Match.ProtoL4N) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("!Proto L4: %v vs %v", rule.Match.ProtoL4N, pkg.L3.L4Proto))
if anyProtoMatch(rule.Match.ProtoL4N, pkg.L3.L4Proto) {
continue
}
}
// protocols layer 5
if rule.Match.ProtoL5 != nil && pkg.L4.L5Proto != meta.ProtoNone {
ruleDebug(pkg, rid, fmt.Sprintf("Proto L5: %v vs %v", rule.Match.ProtoL5, pkg.L4.L5Proto))
if !anyProtoMatch(rule.Match.ProtoL5, pkg.L4.L5Proto) {
continue
}
}
if rule.Match.ProtoL5N != nil && pkg.L4.L5Proto != meta.ProtoNone {
ruleDebug(pkg, rid, fmt.Sprintf("!Proto L5: %v vs %v", rule.Match.ProtoL5N, pkg.L4.L5Proto))
if anyProtoMatch(rule.Match.ProtoL5N, pkg.L4.L5Proto) {
continue
}
}
// source port
if rule.Match.SrcPort != nil && len(rule.Match.SrcPort) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("SPort: %v vs %v", rule.Match.SrcPort, pkg.L4.SrcPort))
if !anyPortMatch(rule.Match.SrcPort, pkg.L4.SrcPort) {
continue
}
}
if rule.Match.SrcPortN != nil && len(rule.Match.SrcPortN) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("!SPort: %v vs %v", rule.Match.SrcPortN, pkg.L4.SrcPort))
if anyPortMatch(rule.Match.SrcPortN, pkg.L4.SrcPort) {
continue
}
}
// destination port
if rule.Match.DestPort != nil && len(rule.Match.DestPort) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("DPort: %v vs %v", rule.Match.DestPort, pkg.L4.DestPort))
if !anyPortMatch(rule.Match.DestPort, pkg.L4.DestPort) {
continue
}
}
if rule.Match.DestPortN != nil && len(rule.Match.DestPortN) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("!DPort: %v vs %v", rule.Match.DestPortN, pkg.L4.DestPort))
if anyPortMatch(rule.Match.DestPortN, pkg.L4.DestPort) {
continue
}
}
// source network
if rule.Match.SrcNet != nil && len(rule.Match.SrcNet) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("SNet: %v vs %v", rule.Match.SrcNet, pkg.L3.SrcIP))
if !anyNetMatch(rule.Match.SrcNet, pkg.L3.SrcIP) {
continue
}
}
if rule.Match.SrcNetN != nil && len(rule.Match.SrcNetN) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("!SNet: %v vs %v", rule.Match.SrcNetN, pkg.L3.SrcIP))
if anyNetMatch(rule.Match.SrcNetN, pkg.L3.SrcIP) {
continue
}
}
// destination network
if rule.Match.DestNet != nil && len(rule.Match.DestNet) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("DNet: %v vs %v", rule.Match.DestNet, pkg.L3.DestIP))
if !anyNetMatch(rule.Match.DestNet, pkg.L3.DestIP) {
continue
}
}
if rule.Match.DestNetN != nil && len(rule.Match.DestNetN) > 0 {
ruleDebug(pkg, rid, fmt.Sprintf("!DNet: %v vs %v", rule.Match.DestNetN, pkg.L3.DestIP))
if anyNetMatch(rule.Match.DestNetN, pkg.L3.DestIP) {
continue
}
}

ruleDebug(pkg, rid, fmt.Sprintf("Applying action '%v'", reverseFilterAction(rule.Action)))
return applyAction(rule.Action)

}

// implicit deny
log.ConnDebug("filter", parse.PkgSrc(pkg), parse.PkgDest(pkg), "No rule matched - implicit deny")
return applyAction(meta.ActionDeny)
}

func ruleDebug(pkg parse.ParsedPackage, rule_id int, msg string) {
log.ConnDebug("filter", parse.PkgSrc(pkg), parse.PkgDest(pkg), fmt.Sprintf("Rule %v - %s", rule_id, msg))
}

func applyAction(action meta.Action) bool {
if action == meta.ActionAccept {
return true
}
return false
}

func anyProtoMatch(list []meta.Proto, single meta.Proto) bool {
for i := range list {
if list[i] == single {
return true
}
}
return false
}

func anyPortMatch(list []uint16, single uint16) bool {
for i := range list {
if list[i] == single {
return true
}
}
return false
}

func allNetMatch(nets []*net.IPNet, ip net.IP) bool {
for i := range nets {
if !nets[i].Contains(ip) {
return false
}
}
return true
}

func anyNetMatch(nets []*net.IPNet, ip net.IP) bool {
for i := range nets {
if nets[i].Contains(ip) {
return true
}
}
return false
}

func reverseFilterAction(action meta.Action) string {
switch action {
case meta.ActionAccept:
return "accept"
case meta.ActionDeny:
return "deny"
default:
return "unknown"
}
}
5 changes: 3 additions & 2 deletions lib/proc/meta/enum.go
Expand Up @@ -4,9 +4,10 @@ type Proto uint8
type Action uint8

const (
ActionAccept Action = 0
ActionDeny Action = 1
ActionAccept Action = 1
ActionDeny Action = 2

ProtoNone Proto = 0
ProtoL3IP4 Proto = 5
ProtoL3IP6 Proto = 6

Expand Down
31 changes: 23 additions & 8 deletions lib/proc/parse/main.go
Expand Up @@ -19,9 +19,11 @@ func Parse(l4Proto string, conn net.Conn) ParsedPackage {
func parseTcp(conn net.Conn) ParsedPackage {
pkg := ParsedPackage{
L3: &ParsedL3Package{
Proto: meta.ProtoL4Tcp,
L4Proto: meta.ProtoL4Tcp,
},
L4: &ParsedL4Package{
L5Proto: meta.ProtoNone,
},
L4: &ParsedL4Package{},
L4Tcp: &ParsedTcpPackage{},
L5Http: &ParsedHttpPackage{},
}
Expand All @@ -31,7 +33,8 @@ func parseTcp(conn net.Conn) ParsedPackage {
log.ConnErrorS("proc-parse", conn.RemoteAddr().String(), "?", "Failed to resolve TCP source-address")
}
pkg.L3.SrcIP = tcpSrcAddr.IP
pkg.L4.SrcPort = tcpSrcAddr.Port
pkg.L4.SrcPort = uint16(tcpSrcAddr.Port)
pkg.L3.Proto = getL3Proto(pkg.L3.SrcIP)

log.ConnDebug("proc-parse", PkgSrc(pkg), "?", "Parsing TCP connection")

Expand All @@ -52,7 +55,7 @@ func parseTcp(conn net.Conn) ParsedPackage {
log.ConnErrorS("proc-parse", PkgSrc(pkg), "?", "Failed to resolve TCP destination-address")
}
pkg.L3.DestIP = tcpDestAddr.IP
pkg.L4.DestPort = tcpDestAddr.Port
pkg.L4.DestPort = uint16(tcpDestAddr.Port)

// additional
log.ConnDebug("proc-parse", PkgSrc(pkg), PkgDest(pkg), "Processing TCP")
Expand All @@ -63,9 +66,11 @@ func parseTcp(conn net.Conn) ParsedPackage {
func parseUdp(conn net.Conn) ParsedPackage {
pkg := ParsedPackage{
L3: &ParsedL3Package{
Proto: meta.ProtoL4Udp,
L4Proto: meta.ProtoL4Udp,
},
L4: &ParsedL4Package{
L5Proto: meta.ProtoNone,
},
L4: &ParsedL4Package{},
L4Udp: &ParsedUdpPackage{},
}
/*
Expand All @@ -75,8 +80,10 @@ func parseUdp(conn net.Conn) ParsedPackage {
if err != nil {
log.ConnErrorS("proc-parse", PkgSrcIP(pkg), "?", "Failed to get original destination IP")
}
logSrc := raddr.String()
logDst := dstAddr.String()
pkg.L3.SrcIP = raddr.String()
pkg.L3.DestIP = dstAddr.String()
pkg.L3.Proto = getL3Proto(pkg.L3.SrcIP)
*/
/*
udpAddr, err := net.ResolveUDPAddr("tcp", dstIpPort.String())
Expand All @@ -91,3 +98,11 @@ func parseUdp(conn net.Conn) ParsedPackage {

return pkg
}

func getL3Proto(ip net.IP) meta.Proto {
if ip.To4() != nil {
return meta.ProtoL3IP4
} else {
return meta.ProtoL3IP6
}
}
4 changes: 2 additions & 2 deletions lib/proc/parse/pkg.go
Expand Up @@ -23,8 +23,8 @@ type ParsedL3Package struct {
}

type ParsedL4Package struct {
SrcPort int
DestPort int
SrcPort uint16
DestPort uint16
L5Proto meta.Proto
}

Expand Down

0 comments on commit cff176c

Please sign in to comment.