fea: access: support match rules.

This commit is contained in:
Daniel Ding
2025-04-12 16:25:56 +08:00
parent 44079e8e4c
commit b6f1925053
7 changed files with 150 additions and 101 deletions

View File

@@ -1,12 +1,13 @@
package access
import (
"net"
"strings"
"github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/models"
"github.com/luscis/openlan/pkg/network"
"github.com/vishvananda/netlink"
"net"
"strings"
)
type Point struct {
@@ -35,11 +36,15 @@ func NewPoint(config *config.Point) *Point {
}
func (p *Point) Initialize() {
p.worker.listener.AddAddr = p.AddAddr
p.worker.listener.DelAddr = p.DelAddr
p.worker.listener.AddRoutes = p.AddRoutes
p.worker.listener.DelRoutes = p.DelRoutes
p.worker.listener.OnTap = p.OnTap
w := p.worker
w.listener.AddAddr = p.AddAddr
w.listener.DelAddr = p.DelAddr
w.listener.AddRoutes = p.AddRoutes
w.listener.DelRoutes = p.DelRoutes
w.listener.OnTap = p.OnTap
w.listener.Forward = p.Forward
p.MixPoint.Initialize()
}
@@ -49,13 +54,13 @@ func (p *Point) DelAddr(ipStr string) error {
}
ipAddr, err := netlink.ParseAddr(ipStr)
if err != nil {
p.out.Error("Point.AddAddr.ParseCIDR %s: %s", ipStr, err)
p.out.Error("Access.AddAddr.ParseCIDR %s: %s", ipStr, err)
return err
}
if err := netlink.AddrDel(p.link, ipAddr); err != nil {
p.out.Warn("Point.DelAddr.UnsetLinkIp: %s", err)
p.out.Warn("Access.DelAddr.UnsetLinkIp: %s", err)
}
p.out.Info("Point.DelAddr: %s", ipStr)
p.out.Info("Access.DelAddr: %s", ipStr)
p.addr = ""
return nil
}
@@ -66,14 +71,14 @@ func (p *Point) AddAddr(ipStr string) error {
}
ipAddr, err := netlink.ParseAddr(ipStr)
if err != nil {
p.out.Error("Point.AddAddr.ParseCIDR %s: %s", ipStr, err)
p.out.Error("Access.AddAddr.ParseCIDR %s: %s", ipStr, err)
return err
}
if err := netlink.AddrAdd(p.link, ipAddr); err != nil {
p.out.Warn("Point.AddAddr.SetLinkIp: %s", err)
p.out.Warn("Access.AddAddr.SetLinkIp: %s", err)
return err
}
p.out.Info("Point.AddAddr: %s", ipStr)
p.out.Info("Access.AddAddr: %s", ipStr)
p.addr = ipStr
return nil
}
@@ -85,52 +90,52 @@ func (p *Point) UpBr(name string) *netlink.Bridge {
la := netlink.LinkAttrs{TxQLen: -1, Name: name}
br := &netlink.Bridge{LinkAttrs: la}
if link, err := netlink.LinkByName(name); link == nil {
p.out.Warn("Point.UpBr: %s %s", name, err)
p.out.Warn("Access.UpBr: %s %s", name, err)
err := netlink.LinkAdd(br)
if err != nil {
p.out.Warn("Point.UpBr.newBr: %s %s", name, err)
p.out.Warn("Access.UpBr.newBr: %s %s", name, err)
}
}
link, err := netlink.LinkByName(name)
if link == nil {
p.out.Error("Point.UpBr: %s %s", name, err)
p.out.Error("Access.UpBr: %s %s", name, err)
return nil
}
if err := netlink.LinkSetUp(link); err != nil {
p.out.Error("Point.UpBr.LinkUp: %s", err)
p.out.Error("Access.UpBr.LinkUp: %s", err)
}
return br
}
func (p *Point) OnTap(w *TapWorker) error {
p.out.Info("Point.OnTap")
p.out.Info("Access.OnTap")
tap := w.device
name := tap.Name()
if tap.Type() == network.ProviderVir { // virtual device
p.out.Error("Point.OnTap: not support %s", tap.Type())
p.out.Error("Access.OnTap: not support %s", tap.Type())
return nil
}
// kernel device
link, err := netlink.LinkByName(name)
if err != nil {
p.out.Error("Point.OnTap: Get %s: %s", name, err)
p.out.Error("Access.OnTap: Get %s: %s", name, err)
return err
}
if err := netlink.LinkSetMTU(link, p.ipMtu); err != nil {
p.out.Error("Point.OnTap.SetMTU: %s", err)
p.out.Error("Access.OnTap.SetMTU: %s", err)
}
if br := p.UpBr(p.brName); br != nil {
if err := netlink.LinkSetMaster(link, br); err != nil {
p.out.Error("Point.OnTap.AddSlave: Switch dev %s: %s", name, err)
p.out.Error("Access.OnTap.AddSlave: Switch dev %s: %s", name, err)
}
link, err = netlink.LinkByName(p.brName)
if err != nil {
p.out.Error("Point.OnTap: Get %s: %s", p.brName, err)
p.out.Error("Access.OnTap: Get %s: %s", p.brName, err)
}
if p.config.Interface.Cost > 0 {
port := network.NewBrPort(name)
if err := port.Cost(p.config.Interface.Cost); err != nil {
p.out.Error("Point.OnTap: Cost %s: %s", p.brName, err)
p.out.Error("Access.OnTap: Cost %s: %s", p.brName, err)
}
}
}
@@ -156,7 +161,7 @@ func (p *Point) AddBypass(routes []*models.Route) {
addr, dest, _ := net.ParseCIDR(remote + "/32")
gws, err := netlink.RouteGet(addr)
if err != nil || len(gws) == 0 {
p.out.Error("Point.AddBypass: RouteGet %s: %s", addr, err)
p.out.Error("Access.AddBypass: RouteGet %s: %s", addr, err)
return
}
rt := &netlink.Route{
@@ -165,19 +170,19 @@ func (p *Point) AddBypass(routes []*models.Route) {
Gw: gws[0].Gw,
Table: 100,
}
p.out.Debug("Point.AddBypass: %s")
p.out.Debug("Access.AddBypass: %s")
if err := netlink.RouteReplace(rt); err != nil {
p.out.Warn("Point.AddBypass: %s %s", rt.Dst, err)
p.out.Warn("Access.AddBypass: %s %s", rt.Dst, err)
return
}
p.out.Info("Point.AddBypass: route %s via %s", rt.Dst, rt.Gw)
p.out.Info("Access.AddBypass: route %s via %s", rt.Dst, rt.Gw)
ru := netlink.NewRule()
ru.Table = 100
ru.Priority = 16383
if err := netlink.RuleAdd(ru); err != nil {
p.out.Warn("Point.AddBypass: %s %s", ru.Dst, err)
p.out.Warn("Access.AddBypass: %s %s", ru.Dst, err)
}
p.out.Info("Point.AddBypass: %s", ru)
p.out.Info("Access.AddBypass: %s", ru)
p.bypass = rt
for _, rt := range routes {
if rt.Prefix != "0.0.0.0/0" {
@@ -191,11 +196,11 @@ func (p *Point) AddBypass(routes []*models.Route) {
Gw: gw,
Priority: rt.Metric,
}
p.out.Debug("Point.AddBypass: %s", rt0)
p.out.Debug("Access.AddBypass: %s", rt0)
if err := netlink.RouteAdd(&rt0); err != nil {
p.out.Warn("Point.AddBypass: %s %s", rt0.Dst, err)
p.out.Warn("Access.AddBypass: %s %s", rt0.Dst, err)
}
p.out.Info("Point.AddBypass: route %s via %s", rt0.Dst, rt0.Gw)
p.out.Info("Access.AddBypass: route %s via %s", rt0.Dst, rt0.Gw)
_, dst1, _ := net.ParseCIDR("128.0.0.0/1")
rt1 := netlink.Route{
LinkIndex: p.link.Attrs().Index,
@@ -203,11 +208,24 @@ func (p *Point) AddBypass(routes []*models.Route) {
Gw: gw,
Priority: rt.Metric,
}
p.out.Debug("Point.AddBypass: %s", rt1)
p.out.Debug("Access.AddBypass: %s", rt1)
if err := netlink.RouteAdd(&rt1); err != nil {
p.out.Warn("Point.AddBypass: %s %s", rt1.Dst, err)
p.out.Warn("Access.AddBypass: %s %s", rt1.Dst, err)
}
p.out.Info("Access.AddBypass: route %s via %s", rt1.Dst, rt1.Gw)
}
}
func (p *Point) Forward(prefix, nexthop string) {
_, dst, _ := net.ParseCIDR(prefix)
p.out.Info("Access.Forward: %s via %s", prefix, nexthop)
if err := netlink.RouteAdd(&netlink.Route{
Dst: dst,
Gw: net.ParseIP(nexthop),
}); err != nil {
if !strings.Contains(err.Error(), "file exists") {
p.out.Warn("Access.Forward: %s %s", prefix, err)
}
p.out.Info("Point.AddBypass: route %s via %s", rt1.Dst, rt1.Gw)
}
}
@@ -228,12 +246,12 @@ func (p *Point) AddRoutes(routes []*models.Route) error {
Gw: nxt,
Priority: rt.Metric,
}
p.out.Debug("Point.AddRoute: %s", rte)
p.out.Debug("Access.AddRoute: %s", rte)
if err := netlink.RouteAdd(&rte); err != nil {
p.out.Warn("Point.AddRoute: %s %s", rt.Prefix, err)
p.out.Warn("Access.AddRoute: %s %s", rt.Prefix, err)
continue
}
p.out.Info("Point.AddRoutes: route %s via %s", rt.Prefix, rt.NextHop)
p.out.Info("Access.AddRoutes: route %s via %s", rt.Prefix, rt.NextHop)
}
p.routes = routes
return nil
@@ -243,12 +261,12 @@ func (p *Point) DelBypass(routes []*models.Route) {
if !p.config.ByPass || p.bypass == nil {
return
}
p.out.Debug("Point.DelRoute: %s")
p.out.Debug("Access.DelRoute: %s")
rt := p.bypass
if err := netlink.RouteAdd(rt); err != nil {
p.out.Warn("Point.DelRoute: %s %s", rt.Dst, err)
p.out.Warn("Access.DelRoute: %s %s", rt.Dst, err)
}
p.out.Info("Point.DelBypass: route %s via %s", rt.Dst, rt.Gw)
p.out.Info("Access.DelBypass: route %s via %s", rt.Dst, rt.Gw)
p.bypass = nil
for _, rt := range routes {
if rt.Prefix != "0.0.0.0/0" {
@@ -262,11 +280,11 @@ func (p *Point) DelBypass(routes []*models.Route) {
Gw: gw,
Priority: rt.Metric,
}
p.out.Debug("Point.DelBypass: %s", rt0)
p.out.Debug("Access.DelBypass: %s", rt0)
if err := netlink.RouteDel(&rt0); err != nil {
p.out.Warn("Point.DelBypass: %s %s", rt0.Dst, err)
p.out.Warn("Access.DelBypass: %s %s", rt0.Dst, err)
}
p.out.Info("Point.DelBypass: route %s via %s", rt0.Dst, rt0.Gw)
p.out.Info("Access.DelBypass: route %s via %s", rt0.Dst, rt0.Gw)
_, dst1, _ := net.ParseCIDR("128.0.0.0/1")
rt1 := netlink.Route{
LinkIndex: p.link.Attrs().Index,
@@ -274,11 +292,11 @@ func (p *Point) DelBypass(routes []*models.Route) {
Gw: gw,
Priority: rt.Metric,
}
p.out.Debug("Point.DelBypass: %s", rt1)
p.out.Debug("Access.DelBypass: %s", rt1)
if err := netlink.RouteDel(&rt1); err != nil {
p.out.Warn("Point.DelBypass: %s %s", rt1.Dst, err)
p.out.Warn("Access.DelBypass: %s %s", rt1.Dst, err)
}
p.out.Info("Point.DelBypass: route %s via %s", rt1.Dst, rt1.Gw)
p.out.Info("Access.DelBypass: route %s via %s", rt1.Dst, rt1.Gw)
}
}
@@ -300,10 +318,10 @@ func (p *Point) DelRoutes(routes []*models.Route) error {
Priority: rt.Metric,
}
if err := netlink.RouteDel(&rte); err != nil {
p.out.Warn("Point.DelRoute: %s %s", rt.Prefix, err)
p.out.Warn("Access.DelRoute: %s %s", rt.Prefix, err)
continue
}
p.out.Info("Point.DelRoutes: route %s via %s", rt.Prefix, rt.NextHop)
p.out.Info("Access.DelRoutes: route %s via %s", rt.Prefix, rt.NextHop)
}
p.routes = nil
return nil