Compare commits
8 Commits
60e1f4c540
...
04fd45fe97
Author | SHA1 | Date | |
---|---|---|---|
04fd45fe97 | |||
849a584371 | |||
1441afb6e4 | |||
7a356867c3 | |||
23580da495 | |||
345b5ff80b | |||
672464a29e | |||
4a0c0938e6 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
kvas2-go
|
||||||
|
config.yaml
|
34
config.yaml.example
Normal file
34
config.yaml.example
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
appConfig:
|
||||||
|
additionalTTL: 216000
|
||||||
|
chainPrefix: KVAS2_
|
||||||
|
ipsetPrefix: kvas2_
|
||||||
|
linkName: br0
|
||||||
|
targetDNSServerAddress: 127.0.0.1
|
||||||
|
targetDNSServerPort: 53
|
||||||
|
listenDNSPort: 3553
|
||||||
|
groups:
|
||||||
|
- id: d663876a
|
||||||
|
name: Example
|
||||||
|
interface: nwg0
|
||||||
|
fixProtect: false
|
||||||
|
rules:
|
||||||
|
- id: 6f34ee91
|
||||||
|
name: Wildcard Example
|
||||||
|
type: wildcard
|
||||||
|
rule: '*wildcard.example.com'
|
||||||
|
enable: true
|
||||||
|
- id: 00ae5f7c
|
||||||
|
name: RegEx Example
|
||||||
|
type: regex
|
||||||
|
rule: '^.*.regex.example.com$'
|
||||||
|
enable: true
|
||||||
|
- id: 6120dc8a
|
||||||
|
name: Domain Example
|
||||||
|
type: domain
|
||||||
|
rule: 'domain.example.com'
|
||||||
|
enable: true
|
||||||
|
- id: b9751782
|
||||||
|
name: Namespace Example
|
||||||
|
type: namespace
|
||||||
|
rule: 'namespace.example.com'
|
||||||
|
enable: true
|
2
go.mod
2
go.mod
@ -5,10 +5,10 @@ go 1.21
|
|||||||
require (
|
require (
|
||||||
github.com/IGLOU-EU/go-wildcard/v2 v2.0.2
|
github.com/IGLOU-EU/go-wildcard/v2 v2.0.2
|
||||||
github.com/coreos/go-iptables v0.7.0
|
github.com/coreos/go-iptables v0.7.0
|
||||||
github.com/google/uuid v1.6.0
|
|
||||||
github.com/miekg/dns v1.1.63
|
github.com/miekg/dns v1.1.63
|
||||||
github.com/rs/zerolog v1.33.0
|
github.com/rs/zerolog v1.33.0
|
||||||
github.com/vishvananda/netlink v1.3.0
|
github.com/vishvananda/netlink v1.3.0
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -159,6 +159,13 @@ func (g *Group) Sync(records *records.Records) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) NetfilterDHook(table string) error {
|
func (g *Group) NetfilterDHook(table string) error {
|
||||||
|
if g.enabled && g.FixProtect && table == "filter" {
|
||||||
|
err := g.iptables.AppendUnique("filter", "_NDM_SL_FORWARD", "-o", g.Interface, "-m", "state", "--state", "NEW", "-j", "_NDM_SL_PROTECT")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fix protect: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return g.ipsetToLink.NetfilterDHook(table)
|
return g.ipsetToLink.NetfilterDHook(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
kvas2.go
114
kvas2.go
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@ -28,6 +27,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
ErrAlreadyRunning = errors.New("already running")
|
ErrAlreadyRunning = errors.New("already running")
|
||||||
ErrGroupIDConflict = errors.New("group id conflict")
|
ErrGroupIDConflict = errors.New("group id conflict")
|
||||||
|
ErrRuleIDConflict = errors.New("rule id conflict")
|
||||||
)
|
)
|
||||||
|
|
||||||
func randomId() [4]byte {
|
func randomId() [4]byte {
|
||||||
@ -39,7 +39,7 @@ func randomId() [4]byte {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
AdditionalTTL uint32
|
AdditionalTTL uint32
|
||||||
ChainPrefix string
|
ChainPrefix string
|
||||||
IpSetPrefix string
|
IPSetPrefix string
|
||||||
LinkName string
|
LinkName string
|
||||||
TargetDNSServerAddress string
|
TargetDNSServerAddress string
|
||||||
TargetDNSServerPort uint16
|
TargetDNSServerPort uint16
|
||||||
@ -53,7 +53,7 @@ type App struct {
|
|||||||
NetfilterHelper4 *netfilterHelper.NetfilterHelper
|
NetfilterHelper4 *netfilterHelper.NetfilterHelper
|
||||||
NetfilterHelper6 *netfilterHelper.NetfilterHelper
|
NetfilterHelper6 *netfilterHelper.NetfilterHelper
|
||||||
Records *records.Records
|
Records *records.Records
|
||||||
Groups map[[4]byte]*group.Group
|
Groups []*group.Group
|
||||||
|
|
||||||
Link netlink.Link
|
Link netlink.Link
|
||||||
|
|
||||||
@ -63,25 +63,23 @@ type App struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) handleLink(event netlink.LinkUpdate) {
|
func (a *App) handleLink(event netlink.LinkUpdate) {
|
||||||
|
log.Trace().
|
||||||
|
Str("interface", event.Link.Attrs().Name).
|
||||||
|
Str("operstatestr", event.Attrs().OperState.String()).
|
||||||
|
Int("operstate", int(event.Attrs().OperState)).
|
||||||
|
Int("change", int(event.Change)).
|
||||||
|
Msg("interface event")
|
||||||
switch event.Change {
|
switch event.Change {
|
||||||
case 0x00000001:
|
case 0x00000001:
|
||||||
log.Debug().
|
ifaceName := event.Link.Attrs().Name
|
||||||
Str("interface", event.Link.Attrs().Name).
|
for _, group := range a.Groups {
|
||||||
Str("operstatestr", event.Attrs().OperState.String()).
|
if group.Interface != ifaceName {
|
||||||
Int("operstate", int(event.Attrs().OperState)).
|
continue
|
||||||
Msg("interface change")
|
}
|
||||||
switch event.Attrs().OperState {
|
|
||||||
case netlink.OperUp:
|
|
||||||
ifaceName := event.Link.Attrs().Name
|
|
||||||
for _, group := range a.Groups {
|
|
||||||
if group.Interface != ifaceName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err := group.LinkUpdateHook(event)
|
err := group.LinkUpdateHook(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Str("group", hex.EncodeToString(group.ID[:])).Err(err).Msg("error while handling interface up")
|
log.Error().Str("group", group.ID.String()).Err(err).Msg("error while handling interface up")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 0xFFFFFFFF:
|
case 0xFFFFFFFF:
|
||||||
@ -242,9 +240,7 @@ func (a *App) start(ctx context.Context) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to subscribe to link updates: %w", err)
|
return fmt.Errorf("failed to subscribe to link updates: %w", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer close(linkUpdateDone)
|
||||||
close(linkUpdateDone)
|
|
||||||
}()
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Global loop
|
Global loop
|
||||||
@ -287,15 +283,27 @@ func (a *App) Start(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AddGroup(groupModel *models.Group) error {
|
func (a *App) AddGroup(groupModel *models.Group) error {
|
||||||
if _, exists := a.Groups[groupModel.ID]; exists {
|
for _, group := range a.Groups {
|
||||||
return ErrGroupIDConflict
|
if groupModel.ID == group.ID {
|
||||||
|
return ErrGroupIDConflict
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dup := make(map[[4]byte]struct{})
|
||||||
|
for _, rule := range groupModel.Rules {
|
||||||
|
if _, exists := dup[rule.ID]; exists {
|
||||||
|
return ErrRuleIDConflict
|
||||||
|
}
|
||||||
|
dup[rule.ID] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
grp, err := group.NewGroup(groupModel, a.NetfilterHelper4, a.Config.ChainPrefix, a.Config.IpSetPrefix)
|
grp, err := group.NewGroup(groupModel, a.NetfilterHelper4, a.Config.ChainPrefix, a.Config.IPSetPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create group: %w", err)
|
return fmt.Errorf("failed to create group: %w", err)
|
||||||
}
|
}
|
||||||
a.Groups[grp.ID] = grp
|
a.Groups = append(a.Groups, grp)
|
||||||
|
|
||||||
|
log.Trace().Str("id", grp.ID.String()).Str("name", grp.Name).Msg("added group")
|
||||||
|
|
||||||
return grp.Sync(a.Records)
|
return grp.Sync(a.Records)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +378,7 @@ func (a *App) processCNameRecord(cNameRecord dns.CNAME) {
|
|||||||
|
|
||||||
ttlDuration := cNameRecord.Hdr.Ttl + a.Config.AdditionalTTL
|
ttlDuration := cNameRecord.Hdr.Ttl + a.Config.AdditionalTTL
|
||||||
|
|
||||||
a.Records.AddCNameRecord(cNameRecord.Hdr.Name[:len(cNameRecord.Hdr.Name)-1], cNameRecord.Target, ttlDuration)
|
a.Records.AddCNameRecord(cNameRecord.Hdr.Name[:len(cNameRecord.Hdr.Name)-1], cNameRecord.Target[:len(cNameRecord.Target)-1], ttlDuration)
|
||||||
|
|
||||||
// TODO: Optimization
|
// TODO: Optimization
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@ -423,12 +431,52 @@ func (a *App) handleMessage(msg dns.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config Config) (*App, error) {
|
func (a *App) ImportConfig(cfg models.ConfigFile) error {
|
||||||
|
a.Config = Config{
|
||||||
|
AdditionalTTL: cfg.AppConfig.AdditionalTTL,
|
||||||
|
ChainPrefix: cfg.AppConfig.ChainPrefix,
|
||||||
|
IPSetPrefix: cfg.AppConfig.IPSetPrefix,
|
||||||
|
LinkName: cfg.AppConfig.LinkName,
|
||||||
|
TargetDNSServerAddress: cfg.AppConfig.TargetDNSServerAddress,
|
||||||
|
TargetDNSServerPort: cfg.AppConfig.TargetDNSServerPort,
|
||||||
|
ListenDNSPort: cfg.AppConfig.ListenDNSPort,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) ExportConfig() models.ConfigFile {
|
||||||
|
groups := make([]models.Group, len(a.Groups))
|
||||||
|
for idx, group := range a.Groups {
|
||||||
|
groups[idx] = *group.Group
|
||||||
|
}
|
||||||
|
return models.ConfigFile{
|
||||||
|
AppConfig: models.AppConfig{
|
||||||
|
AdditionalTTL: a.Config.AdditionalTTL,
|
||||||
|
ChainPrefix: a.Config.ChainPrefix,
|
||||||
|
IPSetPrefix: a.Config.IPSetPrefix,
|
||||||
|
LinkName: a.Config.LinkName,
|
||||||
|
TargetDNSServerAddress: a.Config.TargetDNSServerAddress,
|
||||||
|
TargetDNSServerPort: a.Config.TargetDNSServerPort,
|
||||||
|
ListenDNSPort: a.Config.ListenDNSPort,
|
||||||
|
},
|
||||||
|
Groups: groups,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(config models.ConfigFile) (*App, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
app := &App{}
|
app := &App{}
|
||||||
|
|
||||||
app.Config = config
|
app.Config = Config{
|
||||||
|
AdditionalTTL: config.AppConfig.AdditionalTTL,
|
||||||
|
ChainPrefix: config.AppConfig.ChainPrefix,
|
||||||
|
IPSetPrefix: config.AppConfig.IPSetPrefix,
|
||||||
|
LinkName: config.AppConfig.LinkName,
|
||||||
|
TargetDNSServerAddress: config.AppConfig.TargetDNSServerAddress,
|
||||||
|
TargetDNSServerPort: config.AppConfig.TargetDNSServerPort,
|
||||||
|
ListenDNSPort: config.AppConfig.ListenDNSPort,
|
||||||
|
}
|
||||||
|
|
||||||
app.DNSMITM = dnsMitmProxy.New()
|
app.DNSMITM = dnsMitmProxy.New()
|
||||||
app.DNSMITM.TargetDNSServerAddress = app.Config.TargetDNSServerAddress
|
app.DNSMITM.TargetDNSServerAddress = app.Config.TargetDNSServerAddress
|
||||||
@ -468,7 +516,6 @@ func New(config Config) (*App, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.Records = records.New()
|
app.Records = records.New()
|
||||||
app.Groups = make(map[[4]byte]*group.Group)
|
|
||||||
|
|
||||||
link, err := netlink.LinkByName(app.Config.LinkName)
|
link, err := netlink.LinkByName(app.Config.LinkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -496,7 +543,12 @@ func New(config Config) (*App, error) {
|
|||||||
return nil, fmt.Errorf("failed to clear iptables: %w", err)
|
return nil, fmt.Errorf("failed to clear iptables: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Groups = make(map[[4]byte]*group.Group)
|
for _, group := range config.Groups {
|
||||||
|
err = app.AddGroup(&group)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return app, nil
|
return app, nil
|
||||||
}
|
}
|
||||||
|
25
main.go
25
main.go
@ -6,22 +6,29 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"kvas2-go/models"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
|
|
||||||
app, err := New(Config{
|
cfgFile, err := os.ReadFile("config.yaml")
|
||||||
AdditionalTTL: 216000, // 1 hour
|
if err != nil {
|
||||||
ChainPrefix: "KVAS2_",
|
log.Fatal().Err(err).Msg("failed to read config.yaml")
|
||||||
IpSetPrefix: "kvas2_",
|
}
|
||||||
LinkName: "br0",
|
|
||||||
TargetDNSServerAddress: "127.0.0.1",
|
cfg := models.ConfigFile{}
|
||||||
TargetDNSServerPort: 53,
|
err = yaml.Unmarshal(cfgFile, &cfg)
|
||||||
ListenDNSPort: 3553,
|
if err != nil {
|
||||||
})
|
log.Fatal().Err(err).Msg("failed to parse config.yaml")
|
||||||
|
}
|
||||||
|
|
||||||
|
app, err := New(cfg)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("failed to initialize application")
|
log.Fatal().Err(err).Msg("failed to initialize application")
|
||||||
}
|
}
|
||||||
|
16
models/config.go
Normal file
16
models/config.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type ConfigFile struct {
|
||||||
|
AppConfig AppConfig `yaml:"appConfig"`
|
||||||
|
Groups []Group `yaml:"groups"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppConfig struct {
|
||||||
|
AdditionalTTL uint32 `yaml:"additionalTTL"`
|
||||||
|
ChainPrefix string `yaml:"chainPrefix"`
|
||||||
|
IPSetPrefix string `yaml:"ipsetPrefix"`
|
||||||
|
LinkName string `yaml:"linkName"`
|
||||||
|
TargetDNSServerAddress string `yaml:"targetDNSServerAddress"`
|
||||||
|
TargetDNSServerPort uint16 `yaml:"targetDNSServerPort"`
|
||||||
|
ListenDNSPort uint16 `yaml:"listenDNSPort"`
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
type Group struct {
|
type Group struct {
|
||||||
ID [4]byte
|
ID ID `yaml:"id"`
|
||||||
Name string
|
Name string `yaml:"name"`
|
||||||
Interface string
|
Interface string `yaml:"interface"`
|
||||||
Rules []*Rule
|
FixProtect bool `yaml:"fixProtect"`
|
||||||
FixProtect bool
|
Rules []*Rule `yaml:"rules"`
|
||||||
}
|
}
|
||||||
|
20
models/id.go
Normal file
20
models/id.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ID [4]byte
|
||||||
|
|
||||||
|
func (id *ID) String() string {
|
||||||
|
return hex.EncodeToString(id[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (id *ID) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(id.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (id *ID) UnmarshalText(data []byte) error {
|
||||||
|
_, err := hex.Decode(id[:], data)
|
||||||
|
return err
|
||||||
|
}
|
@ -2,16 +2,17 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IGLOU-EU/go-wildcard/v2"
|
"github.com/IGLOU-EU/go-wildcard/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
ID [4]byte
|
ID ID `yaml:"id"`
|
||||||
Name string
|
Name string `yaml:"name"`
|
||||||
Type string
|
Type string `yaml:"type"`
|
||||||
Rule string
|
Rule string `yaml:"rule"`
|
||||||
Enable bool
|
Enable bool `yaml:"enable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Rule) IsEnabled() bool {
|
func (d *Rule) IsEnabled() bool {
|
||||||
@ -25,8 +26,13 @@ func (d *Rule) IsMatch(domainName string) bool {
|
|||||||
case "regex":
|
case "regex":
|
||||||
ok, _ := regexp.MatchString(d.Rule, domainName)
|
ok, _ := regexp.MatchString(d.Rule, domainName)
|
||||||
return ok
|
return ok
|
||||||
case "plaintext":
|
case "domain":
|
||||||
return domainName == d.Rule
|
return domainName == d.Rule
|
||||||
|
case "namespace":
|
||||||
|
if domainName == d.Rule {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return strings.HasSuffix(domainName, "."+d.Rule)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,11 @@ func (r *IPSetToLink) insertIPRoute() error {
|
|||||||
// Find interface
|
// Find interface
|
||||||
iface, err := netlink.LinkByName(r.IfaceName)
|
iface, err := netlink.LinkByName(r.IfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// TODO: Нормально отлавливать ошибку
|
||||||
|
if err.Error() == "Link not found" {
|
||||||
|
// TODO: Логи
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("error while getting interface: %w", err)
|
return fmt.Errorf("error while getting interface: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,9 +146,12 @@ func (r *IPSetToLink) insertIPRoute() error {
|
|||||||
Dst: &net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}},
|
Dst: &net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}},
|
||||||
}
|
}
|
||||||
// Delete rule if exists
|
// Delete rule if exists
|
||||||
_ = netlink.RouteDel(route)
|
|
||||||
err = netlink.RouteAdd(route)
|
err = netlink.RouteAdd(route)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// TODO: Нормально отлавливать ошибку
|
||||||
|
if err.Error() == "file exists" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("error while mapping iface with table: %w", err)
|
return fmt.Errorf("error while mapping iface with table: %w", err)
|
||||||
}
|
}
|
||||||
r.ipRoute = route
|
r.ipRoute = route
|
||||||
@ -273,7 +281,7 @@ func (r *IPSetToLink) NetfilterDHook(table string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPSetToLink) LinkUpdateHook(event netlink.LinkUpdate) error {
|
func (r *IPSetToLink) LinkUpdateHook(event netlink.LinkUpdate) error {
|
||||||
if !r.enabled || event.Change != 1 || event.Link.Attrs().Name != r.IfaceName || event.Attrs().OperState != netlink.OperUp {
|
if !r.enabled || event.Change != 1 || event.Link.Attrs().Name != r.IfaceName {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return r.insertIPRoute()
|
return r.insertIPRoute()
|
||||||
|
@ -27,11 +27,18 @@ func (nh *NetfilterHelper) CleanIPTables(chainPrefix string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
if strings.Contains(rule, jumpToChainPrefix) {
|
if !strings.Contains(rule, jumpToChainPrefix) {
|
||||||
err = nh.IPTables.Delete(table, chain, rule)
|
continue
|
||||||
if err != nil {
|
}
|
||||||
return fmt.Errorf("rule deletion error: %w", err)
|
|
||||||
}
|
ruleSlice := strings.Split(rule, " ")
|
||||||
|
if len(ruleSlice) < 2 || ruleSlice[0] != "-A" || ruleSlice[1] != chain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nh.IPTables.Delete(table, chain, ruleSlice[2:]...)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("rule deletion error: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user