支持DST-MAC

This commit is contained in:
mlkt 2024-08-07 21:46:14 +08:00
parent fa919737c1
commit d1a78581aa
3 changed files with 39 additions and 22 deletions

View File

@ -9,8 +9,9 @@ const (
GEOSITE GEOSITE
GEOIP GEOIP
SrcGEOIP SrcGEOIP
IPASN
SrcMAC SrcMAC
DstMAC
IPASN
SrcIPASN SrcIPASN
IPCIDR IPCIDR
SrcIPCIDR SrcIPCIDR
@ -55,10 +56,12 @@ func (rt RuleType) String() string {
return "GeoIP" return "GeoIP"
case SrcGEOIP: case SrcGEOIP:
return "SrcGeoIP" return "SrcGeoIP"
case IPASN:
return "IPASN"
case SrcMAC: case SrcMAC:
return "SrcMAC" return "SrcMAC"
case DstMAC:
return "DstMAC"
case IPASN:
return "IPASN"
case SrcIPASN: case SrcIPASN:
return "SrcIPASN" return "SrcIPASN"
case IPCIDR: case IPCIDR:

View File

@ -19,21 +19,27 @@ var arpTable = make(map[string]string)
const reloadInterval = 5 * time.Minute const reloadInterval = 5 * time.Minute
var startOnce sync.Once var startOnce sync.Once
func init() { func init() {
} }
type SrcMAC struct { type MacAddr struct {
*Base *Base
mac string mac string
adapter string adapter string
isSourceIP bool
} }
func (d *SrcMAC) RuleType() C.RuleType { func (d *MacAddr) RuleType() C.RuleType {
if d.isSourceIP {
return C.SrcMAC return C.SrcMAC
} else {
return C.DstMAC
}
} }
func getLoadArpTableFunc() func() (string, error) { func getLoadArpTableFunc() func() (string, error) {
const ipv6Error = "can't load ipv6 arp table, SRC-MAC rule can't match src ipv6 address" const ipv6Error = "can't load ipv6 arp table, SRC-MAC/DST-MAC rule can't match src ipv6 address"
getIpv4Only := func() (string, error) { getIpv4Only := func() (string, error) {
return cmd.ExecCmd("arp -a") return cmd.ExecCmd("arp -a")
@ -95,39 +101,45 @@ func getLoadArpTableFunc() func() (string, error) {
} }
} }
func (d *SrcMAC) Match(metadata *C.Metadata) (bool, string) { func (d *MacAddr) Match(metadata *C.Metadata) (bool, string) {
table := getArpTable() table := getArpTable()
srcIP := metadata.SrcIP.String() var ip string
mac, exists := table[srcIP] if d.isSourceIP {
ip = metadata.SrcIP.String()
} else {
ip = metadata.DstIP.String()
}
mac, exists := table[ip]
if exists { if exists {
if mac == d.mac { if mac == d.mac {
return true, d.adapter return true, d.adapter
} }
} else { } else {
log.Warnln("can't find the IP address in arp table: %s", srcIP) log.Infoln("can't find the IP address in arp table: %s", ip)
} }
return false, d.adapter return false, d.adapter
} }
func (d *SrcMAC) Adapter() string { func (d *MacAddr) Adapter() string {
return d.adapter return d.adapter
} }
func (d *SrcMAC) Payload() string { func (d *MacAddr) Payload() string {
return d.mac return d.mac
} }
var macRegex = regexp.MustCompile(`^([0-9a-f]{2}:){5}[0-9a-f]{2}$`) var macRegex = regexp.MustCompile(`^([0-9a-f]{2}:){5}[0-9a-f]{2}$`)
func NewMAC(mac string, adapter string) (*SrcMAC, error) { func NewMAC(mac string, adapter string, isSrc bool) (*MacAddr, error) {
macAddr := strings.ReplaceAll(strings.ToLower(mac), "-", ":") macAddr := strings.ReplaceAll(strings.ToLower(mac), "-", ":")
if !macRegex.MatchString(macAddr) { if !macRegex.MatchString(macAddr) {
return nil, errors.New("mac address format error: " + mac) return nil, errors.New("mac address format error: " + mac)
} }
return &SrcMAC{ return &MacAddr{
Base: &Base{}, Base: &Base{},
mac: macAddr, mac: macAddr,
adapter: adapter, adapter: adapter,
isSourceIP: isSrc,
}, nil }, nil
} }

View File

@ -26,11 +26,13 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string]
parsed, parseErr = RC.NewGEOIP(payload, target, false, noResolve) parsed, parseErr = RC.NewGEOIP(payload, target, false, noResolve)
case "SRC-GEOIP": case "SRC-GEOIP":
parsed, parseErr = RC.NewGEOIP(payload, target, true, true) parsed, parseErr = RC.NewGEOIP(payload, target, true, true)
case "SRC-MAC":
parsed, parseErr = RC.NewMAC(payload, target, true)
case "DST-MAC":
parsed, parseErr = RC.NewMAC(payload, target, false)
case "IP-ASN": case "IP-ASN":
noResolve := RC.HasNoResolve(params) noResolve := RC.HasNoResolve(params)
parsed, parseErr = RC.NewIPASN(payload, target, false, noResolve) parsed, parseErr = RC.NewIPASN(payload, target, false, noResolve)
case "SRC-MAC":
parsed, parseErr = RC.NewMAC(payload, target)
case "SRC-IP-ASN": case "SRC-IP-ASN":
parsed, parseErr = RC.NewIPASN(payload, target, true, true) parsed, parseErr = RC.NewIPASN(payload, target, true, true)
case "IP-CIDR", "IP-CIDR6": case "IP-CIDR", "IP-CIDR6":