catch interface up/down

This commit is contained in:
Vladimir Avtsenov 2024-09-06 15:48:15 +03:00
parent 319e75fd15
commit 1015423a8f
3 changed files with 80 additions and 22 deletions

View File

@ -10,7 +10,7 @@ Realized features:
- [X] IPSet integration
- [X] IP integration
- [X] IPTables rules to IPSet
- [ ] Catch interface up/down
- [X] Catch interface up/down
- [ ] Catch `netfilter.d` event
- [ ] Rule composer (CRUD)
- [ ] GORM integration

View File

@ -13,6 +13,7 @@ import (
"kvas2-go/netfilter-helper"
"github.com/rs/zerolog/log"
"github.com/vishvananda/netlink"
)
var (
@ -98,10 +99,53 @@ func (a *App) Listen(ctx context.Context) []error {
}
}()
link := make(chan netlink.LinkUpdate)
done := make(chan struct{})
netlink.LinkSubscribe(link, done)
Loop:
for {
select {
case <-ctx.Done():
case <-isError:
case event := <-link:
switch event.Change {
case 0x00000001:
log.Debug().
Str("interface", event.Link.Attrs().Name).
Str("operstatestr", event.Attrs().OperState.String()).
Int("operstate", int(event.Attrs().OperState)).
Msg("interface change")
if event.Attrs().OperState != netlink.OperDown {
for _, group := range a.Groups {
if group.Interface == event.Link.Attrs().Name {
err = group.ifaceToIPSet.IfaceHandle()
if err != nil {
log.Error().Int("group", group.ID).Err(err).Msg("error while handling interface up")
}
}
}
}
case 0xFFFFFFFF:
switch event.Header.Type {
case 16:
log.Debug().
Str("interface", event.Link.Attrs().Name).
Int("type", int(event.Header.Type)).
Msg("interface add")
case 17:
log.Debug().
Str("interface", event.Link.Attrs().Name).
Int("type", int(event.Header.Type)).
Msg("interface del")
}
}
case <-ctx.Done():
break Loop
case <-isError:
break Loop
}
}
close(done)
errs2 := a.dnsOverrider.Disable()
if errs2 != nil {

View File

@ -25,18 +25,41 @@ type IfaceToIPSet struct {
ipRoute *netlink.Route
}
func (r *IfaceToIPSet) IfaceHandle() error {
// Find interface
iface, err := netlink.LinkByName(r.IfaceName)
if err != nil {
log.Warn().Str("interface", r.IfaceName).Err(err).Msg("error while getting interface")
}
// Mapping iface with table
if iface != nil {
route := &netlink.Route{
LinkIndex: iface.Attrs().Index,
Table: r.table,
Dst: &net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}},
}
// Delete rule if exists
err = netlink.RouteDel(route)
if err != nil {
log.Warn().Str("interface", r.IfaceName).Err(err).Msg("error while deleting route")
}
err = netlink.RouteAdd(route)
if err != nil {
return fmt.Errorf("error while mapping iface with table: %w", err)
}
r.ipRoute = route
}
return nil
}
func (r *IfaceToIPSet) ForceEnable() error {
// Release used mark and table
r.Disable()
r.mark = 0
r.table = 0
// Find interface
iface, err := netlink.LinkByName(r.IfaceName)
if err != nil {
log.Warn().Str("interface", r.IfaceName).Msg("error while getting interface")
}
// Find unused mark and table
markMap := make(map[uint32]struct{})
tableMap := map[int]struct{}{0: {}, 253: {}, 254: {}, 255: {}}
@ -152,18 +175,9 @@ func (r *IfaceToIPSet) ForceEnable() error {
}
r.ipRule = rule
// Mapping iface with table
if iface != nil {
route := &netlink.Route{
LinkIndex: iface.Attrs().Index,
Table: rule.Table,
Dst: &net.IPNet{IP: []byte{0, 0, 0, 0}, Mask: []byte{0, 0, 0, 0}},
}
err = netlink.RouteAdd(route)
err = r.IfaceHandle()
if err != nil {
return fmt.Errorf("error while mapping iface with table: %w", err)
}
r.ipRoute = route
return nil
}
return nil