From 5220f9b14ca6c42c77e3f25bd3bf65258f40b758 Mon Sep 17 00:00:00 2001 From: Daniel Ding Date: Fri, 14 Jun 2024 22:30:26 +0800 Subject: [PATCH] fix: vrf not clear --- .../openlan/switch/network/ipsec.json.example | 32 ++ .../openlan/switch/network/v1024.json.example | 16 - dist/rootfs/var/openlan/script/ipsec.sh | 6 +- pkg/config/fabric.go | 63 --- pkg/config/ipsec.go | 28 + pkg/config/network.go | 10 +- pkg/models/ipsec_others.go | 6 - pkg/switch/fabric.go | 510 ------------------ pkg/switch/ipsec.go | 230 ++++++++ pkg/switch/network.go | 167 +----- pkg/switch/vxlan.go | 51 -- 11 files changed, 308 insertions(+), 811 deletions(-) create mode 100755 dist/rootfs/etc/openlan/switch/network/ipsec.json.example delete mode 100755 dist/rootfs/etc/openlan/switch/network/v1024.json.example delete mode 100755 pkg/config/fabric.go create mode 100644 pkg/config/ipsec.go delete mode 100644 pkg/models/ipsec_others.go delete mode 100644 pkg/switch/fabric.go create mode 100644 pkg/switch/ipsec.go delete mode 100755 pkg/switch/vxlan.go diff --git a/dist/rootfs/etc/openlan/switch/network/ipsec.json.example b/dist/rootfs/etc/openlan/switch/network/ipsec.json.example new file mode 100755 index 0000000..4911e78 --- /dev/null +++ b/dist/rootfs/etc/openlan/switch/network/ipsec.json.example @@ -0,0 +1,32 @@ +{ + "name": "ipsec", + "provider": "ipsec", + "specifies": { + "tunnels": [ + { + "remote": "3.3.2.1", + "secret": "d7ecd73ccc25", + "transport": "gre" + }, + { + "remote": "3.3.2.2", + "secret": "d7ecd73ccc25", + "transport": "gre" + }, + { + "localid": "@con1.ipsec.com", + "remote": "3.3.3.1", + "remoteport": "4501", + "secret": "d7ecd73ccc25", + "transport": "vxlan" + }, + { + "localport": "4501", + "remote": "3.3.3.2", + "remoteid": "@con1.ipsec.com", + "secret": "d7ecd73ccc25", + "transport": "vxlan" + } + ] + } +} \ No newline at end of file diff --git a/dist/rootfs/etc/openlan/switch/network/v1024.json.example b/dist/rootfs/etc/openlan/switch/network/v1024.json.example deleted file mode 100755 index 4e585e8..0000000 --- a/dist/rootfs/etc/openlan/switch/network/v1024.json.example +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "v1024", - "provider": "vxlan", - "specifies": { - "vni": 1024, - "fabric": "fabric" - }, - "bridge": { - "address": "192.168.55.1/24" - }, - "subnet": { - "startAt": "192.168.55.100", - "endAt": "192.168.55.130" - }, - "dhcp": "enable" -} diff --git a/dist/rootfs/var/openlan/script/ipsec.sh b/dist/rootfs/var/openlan/script/ipsec.sh index 010f2c9..a004bf9 100644 --- a/dist/rootfs/var/openlan/script/ipsec.sh +++ b/dist/rootfs/var/openlan/script/ipsec.sh @@ -13,4 +13,8 @@ set -ex /usr/sbin/ipsec --checknss ## Start pluto -/usr/libexec/ipsec/pluto --leak-detective --config /etc/ipsec.conf --nofork \ No newline at end of file +/usr/libexec/ipsec/pluto --leak-detective --config /etc/ipsec.conf --nofork + +## Clear xfrm +/sbin/ip xfrm policy flush +/sbin/ip xfrm state flush \ No newline at end of file diff --git a/pkg/config/fabric.go b/pkg/config/fabric.go deleted file mode 100755 index 8dbbcd1..0000000 --- a/pkg/config/fabric.go +++ /dev/null @@ -1,63 +0,0 @@ -package config - -type FabricSpecifies struct { - Mss int `json:"tcpMss,omitempty"` - Fragment bool `json:"fragment"` - Driver string `json:"driver,omitempty"` - Name string `json:"name,omitempty"` - Tunnels []*FabricTunnel `json:"tunnels"` -} - -func (n *FabricSpecifies) Correct() { - for _, tun := range n.Tunnels { - tun.Correct() - if tun.DstPort == 0 { - if n.Driver == "stt" { - tun.DstPort = 7471 - } else { - tun.DstPort = 4789 // 8472 - } - } - } -} - -func (n *FabricSpecifies) AddTunnel(obj *FabricTunnel) { - found := -1 - for index, tun := range n.Tunnels { - if tun.Remote != obj.Remote { - continue - } - found = index - n.Tunnels[index] = obj - break - } - if found < 0 { - n.Tunnels = append(n.Tunnels, obj) - } -} - -func (n *FabricSpecifies) DelTunnel(remote string) bool { - found := -1 - for index, tun := range n.Tunnels { - if tun.Remote != remote { - continue - } - found = index - break - } - if found >= 0 { - copy(n.Tunnels[found:], n.Tunnels[found+1:]) - n.Tunnels = n.Tunnels[:len(n.Tunnels)-1] - } - return found >= 0 -} - -type FabricTunnel struct { - DstPort uint32 `json:"destPort"` - Remote string `json:"remote"` - Local string `json:"local,omitempty"` - Mode string `json:"mode,omitempty"` -} - -func (c *FabricTunnel) Correct() { -} diff --git a/pkg/config/ipsec.go b/pkg/config/ipsec.go new file mode 100644 index 0000000..5d9216c --- /dev/null +++ b/pkg/config/ipsec.go @@ -0,0 +1,28 @@ +package config + +type IPSecTunnel struct { + Left string `json:"local"` + LeftId string `json:"localid"` + LeftPort string `json:"localport"` + Right string `json:"remote"` + RightId string `json:"remoteid"` + RightPort string `json:"remoteport"` + Transport string `json:"transport"` +} + +func (s *IPSecTunnel) Correct() { + if s.Left == "" { + s.Left = "%defaultroute" + } +} + +type IPSecSpecifies struct { + Name string `json:"name"` + Tunnels []IPSecTunnel `json:"tunnels"` +} + +func (s *IPSecSpecifies) Correct() { + for _, t := range s.Tunnels { + t.Correct() + } +} diff --git a/pkg/config/network.go b/pkg/config/network.go index cc3c2d7..267bc93 100755 --- a/pkg/config/network.go +++ b/pkg/config/network.go @@ -31,8 +31,8 @@ type Network struct { func (n *Network) NewSpecifies() interface{} { switch n.Provider { - case "vxlan": - n.Specifies = &VxLANSpecifies{} + case "ipsec": + n.Specifies = &IPSecSpecifies{} case "router": n.Specifies = &RouterSpecifies{} default: @@ -55,6 +55,12 @@ func (n *Network) Correct(sw *Switch) { obj.Correct() obj.Name = n.Name } + case "ipsec": + spec := n.Specifies + if obj, ok := spec.(*IPSecSpecifies); ok { + obj.Correct() + obj.Name = n.Name + } } if n.Subnet == nil { n.Subnet = &Subnet{} diff --git a/pkg/models/ipsec_others.go b/pkg/models/ipsec_others.go deleted file mode 100644 index 7d5f5ee..0000000 --- a/pkg/models/ipsec_others.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build !linux - -package models - -func (l *EspState) Update() { -} diff --git a/pkg/switch/fabric.go b/pkg/switch/fabric.go deleted file mode 100644 index b7bbe61..0000000 --- a/pkg/switch/fabric.go +++ /dev/null @@ -1,510 +0,0 @@ -package cswitch - -import ( - "fmt" - "strings" - - "github.com/danieldin95/go-openvswitch/ovs" - "github.com/luscis/openlan/pkg/api" - co "github.com/luscis/openlan/pkg/config" - "github.com/luscis/openlan/pkg/libol" - cn "github.com/luscis/openlan/pkg/network" - nl "github.com/vishvananda/netlink" -) - -type Fabricer interface { - AddNetwork(cfg *co.Network) - DelNetwork(bridge string, vni uint32) - TcpMss() int -} - -var fabrics = make(map[string]Fabricer) - -func GetFabricer(name string) Fabricer { - return fabrics[name] -} - -type OvsBridge struct { - name string - cli *ovs.Client - out *libol.SubLogger -} - -func NewOvsBridge(name string) *OvsBridge { - return &OvsBridge{ - name: name, - cli: ovs.New(), - out: libol.NewSubLogger(name), - } -} - -func (o *OvsBridge) delFlow(flow *ovs.MatchFlow) error { - if err := o.cli.OpenFlow.DelFlows(o.name, flow); err != nil { - o.out.Warn("OvsBridge.addFlow %s", err) - return err - } - return nil -} - -func (o *OvsBridge) addFlow(flow *ovs.Flow) error { - if err := o.cli.OpenFlow.AddFlow(o.name, flow); err != nil { - o.out.Warn("OvsBridge.addFlow %s", err) - return err - } - return nil -} - -func (o *OvsBridge) setDown() error { - if err := o.cli.VSwitch.DeleteBridge(o.name); err != nil { - o.out.Error("OvsBridge.DeleteBridge %s %s", o.name, err) - return err - } - return nil -} - -func (o *OvsBridge) setUp() error { - if err := o.cli.VSwitch.AddBridge(o.name); err != nil { - o.out.Error("OvsBridge.AddBridge %s %s", o.name, err) - return err - } - return nil -} - -func (o *OvsBridge) setMode(mode ovs.FailMode) error { - if err := o.cli.VSwitch.SetFailMode(o.name, mode); err != nil { - o.out.Warn("OvsBridge.setMode %s %s", mode, err) - return err - } - return nil -} - -func (o *OvsBridge) addPort(name string, options *ovs.InterfaceOptions) error { - if err := o.cli.VSwitch.AddPort(o.name, name); err != nil { - o.out.Warn("OvsBridge.addPort %s %s", name, err) - return err - } - if options == nil { - return nil - } - if err := o.cli.VSwitch.Set.Interface(name, *options); err != nil { - o.out.Warn("OvsBridge.addPort %s %s", name, err) - return err - } - return nil -} - -func (o *OvsBridge) delPort(name string) error { - if err := o.cli.VSwitch.DeletePort(o.name, name); err != nil { - o.out.Warn("OvsBridge.delPort %s %s", name, err) - return err - } - return nil -} - -func (o *OvsBridge) setPort(name string, options ovs.InterfaceOptions) error { - if err := o.cli.VSwitch.Set.Interface(name, options); err != nil { - o.out.Warn("OvsBridge.setPort %s %s", name, err) - return err - } - return nil -} - -func (o *OvsBridge) dumpPort(name string) *ovs.PortStats { - if port, err := o.cli.OpenFlow.DumpPort(o.name, name); err != nil { - o.out.Warn("OvsBridge.dumpPort %s %s", name, err) - return nil - } else { - return port - } -} - -const ( - TLsToTun = 2 // From a switch include border to tunnels. - TTunToLs = 4 // From tunnels to a switch. - TSourceLearn = 10 // Learning source mac. - TUcastToTun = 20 // Forwarding by fdb. - TFloodToTun = 30 // Flooding to tunnels or patch by flags. - TFloodToBor = 31 // Flooding to border in a switch. - TFloodLoop = 32 // Flooding to patch in a switch from border. -) - -const ( - FFromLs = 2 // In a logical switch. - FFromTun = 4 // From peer tunnels. -) - -const ( - MatchRegFlag = "reg10" - NxmRegFlag = "NXM_NX_REG10[0..31]" - NxmRegEthDst = "NXM_OF_ETH_DST[]" - NxmRegEthSrc = "NXM_OF_ETH_SRC[]" - NxmRegTunId = "NXM_NX_TUN_ID[0..31]" - NxmRegInPort = "NXM_OF_IN_PORT[]" -) - -type OvsPort struct { - name string - portId int - options ovs.InterfaceOptions -} - -type FabricWorker struct { - *WorkerImpl - spec *co.FabricSpecifies - ovs *OvsBridge - cookie uint64 - tunnels map[string]*OvsPort - borders map[string]*OvsPort - bridge map[string]*cn.LinuxBridge -} - -func NewFabricWorker(c *co.Network) *FabricWorker { - w := &FabricWorker{ - WorkerImpl: NewWorkerApi(c), - ovs: NewOvsBridge(c.Bridge.Name), - tunnels: make(map[string]*OvsPort, 1024), - borders: make(map[string]*OvsPort, 1024), - bridge: make(map[string]*cn.LinuxBridge, 1024), - } - w.spec, _ = c.Specifies.(*co.FabricSpecifies) - fabrics[c.Name] = w - return w -} - -func (w *FabricWorker) upTables() { - _ = w.ovs.addFlow(&ovs.Flow{ - Actions: []ovs.Action{ovs.Drop()}, - }) - // Table 2: set flags from logical switch. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TLsToTun, - Priority: 1, - Actions: []ovs.Action{ - ovs.Load(libol.Uint2S(FFromLs), NxmRegFlag), - ovs.Resubmit(0, TSourceLearn), - }, - }) - // Table 4: set flags from tunnels. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TTunToLs, - Priority: 1, - Actions: []ovs.Action{ - ovs.Load(libol.Uint2S(FFromTun), NxmRegFlag), - ovs.Resubmit(0, TSourceLearn), - }, - }) - // Table 10: source learning - w.addLearning() - // Table 20: default to flood 30 - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TUcastToTun, - Actions: []ovs.Action{ - ovs.Resubmit(0, TFloodToTun), - }, - }) - // Table 30: default drop. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodToTun, - Actions: []ovs.Action{ovs.Drop()}, - }) - // Table 31: default drop. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodToBor, - Actions: []ovs.Action{ovs.Drop()}, - }) -} - -func (w *FabricWorker) Initialize() { - w.WorkerImpl.Initialize() - if err := w.ovs.setUp(); err != nil { - return - } - _ = w.ovs.setMode("secure") - w.upTables() - api.ListWorker(func(n api.Networker) { - if w.IsSlave(n) { - n.Initialize() - } - }) -} - -func (w *FabricWorker) vni2peer(vni uint32) (string, string) { - tunPort := fmt.Sprintf("vb-%08d", vni) - brPort := fmt.Sprintf("vt-%08d", vni) - return brPort, tunPort -} - -func (w *FabricWorker) UpLink(bridge string, vni uint32, addr string) *ovs.PortStats { - brPort, tunPort := w.vni2peer(vni) - link := &nl.Veth{ - LinkAttrs: nl.LinkAttrs{Name: tunPort}, - PeerName: brPort, - } - if err := nl.LinkAdd(link); err != nil { - w.out.Warn("FabricWorker.addLink %s", err) - } - if err := nl.LinkSetUp(link); err != nil { - w.out.Warn("FabricWorker.setLinkUp %s", err) - } - - // Setup linux bridge for outputs - br := cn.NewLinuxBridge(bridge, 0) - br.Open(addr) - _ = br.AddSlave(brPort) - if err := br.CallIptables(1); err != nil { - w.out.Warn("FabricWorker.IpTables %s", err) - } - - w.bridge[bridge] = br - // Add port to OvS tunnel bridge - _ = w.ovs.addPort(tunPort, nil) - if port := w.ovs.dumpPort(tunPort); port != nil { - return port - } - return nil -} - -func (w *FabricWorker) addLearning() { - // Table 10: source mac learning - learnSpecs := []ovs.Match{ - ovs.FieldMatch(NxmRegTunId, NxmRegTunId), - ovs.FieldMatch(NxmRegEthDst, NxmRegEthSrc), - } - learnActions := []ovs.Action{ - ovs.OutputField(NxmRegInPort), - } - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TSourceLearn, - Actions: []ovs.Action{ - ovs.Learn(&ovs.LearnedFlow{ - Table: TUcastToTun, - Matches: learnSpecs, - Priority: 1, - HardTimeout: 300, - Actions: learnActions, - }), - ovs.Resubmit(0, TUcastToTun), - }, - }) -} - -func (w *FabricWorker) AddNetwork(cfg *co.Network) { - spec, _ := cfg.Specifies.(*co.VxLANSpecifies) - libol.Info("Fabric.AddNetwork %d", spec.Vni) - patch := w.UpLink(cfg.Bridge.Name, spec.Vni, cfg.Bridge.Address) - // Table 0: load tunnel id from patch port. - _ = w.ovs.addFlow(&ovs.Flow{ - InPort: patch.PortID, - Priority: 1, - Actions: []ovs.Action{ - ovs.Load(libol.Uint2S(spec.Vni), NxmRegTunId), - ovs.Resubmit(0, TLsToTun), - }, - }) - // Table 30: flooding to patch from tunnels. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodToTun, - Priority: 2, - Matches: []ovs.Match{ - ovs.FieldMatch(NxmRegTunId, libol.Uint2S(spec.Vni)), - ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromTun)), - }, - Actions: []ovs.Action{ - ovs.Output(patch.PortID), - ovs.Resubmit(0, TFloodToBor), - }, - }) - // Table 32: flooding to patch from border. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodLoop, - Priority: 2, - Matches: []ovs.Match{ - ovs.FieldMatch(NxmRegTunId, libol.Uint2S(spec.Vni)), - ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromLs)), - }, - Actions: []ovs.Action{ - ovs.Output(patch.PortID), - }, - }) -} - -func (w *FabricWorker) Addr2Port(addr, pre string) string { - name := pre + strings.ReplaceAll(addr, ".", "") - return libol.IfName(name) -} - -func (w *FabricWorker) flood2Tunnel() { - var actions []ovs.Action - for _, tun := range w.tunnels { - actions = append(actions, ovs.Output(tun.portId)) - } - actions = append(actions, ovs.Resubmit(0, TFloodToBor)) - // Table 30: Flooding to tunnels from patch. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodToTun, - Priority: 1, - Matches: []ovs.Match{ - ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromLs)), - }, - Actions: actions, - }) -} - -func (w *FabricWorker) flood2Border() { - var actions []ovs.Action - for _, port := range w.borders { - actions = append(actions, ovs.Output(port.portId)) - } - // Table 31: flooding to border from tunnels. - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodToBor, - Priority: 1, - Matches: []ovs.Match{ - ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromTun)), - }, - Actions: actions, - }) - // Table 32: flooding to border from a border. - actions = append(actions, ovs.Resubmit(0, TFloodLoop)) - _ = w.ovs.addFlow(&ovs.Flow{ - Table: TFloodToBor, - Priority: 1, - Matches: []ovs.Match{ - ovs.FieldMatch(MatchRegFlag, libol.Uint2S(FFromLs)), - }, - Actions: actions, - }) -} - -func (w *FabricWorker) tunnelType() ovs.InterfaceType { - if w.spec.Driver == "stt" { - return ovs.InterfaceTypeSTT - } - return ovs.InterfaceTypeVXLAN -} - -func (w *FabricWorker) AddTunnel(cfg co.FabricTunnel) { - name := w.Addr2Port(cfg.Remote, "vx-") - options := ovs.InterfaceOptions{ - Type: w.tunnelType(), - BfdEnable: true, - RemoteIP: cfg.Remote, - Key: "flow", - DstPort: cfg.DstPort, - } - if w.spec.Fragment { - options.DfDefault = "false" - } else { - options.DfDefault = "true" - } - if err := w.ovs.addPort(name, &options); err != nil { - return - } - port := w.ovs.dumpPort(name) - if port == nil { - return - } - if cfg.Mode == "border" { - _ = w.ovs.addFlow(&ovs.Flow{ - InPort: port.PortID, - Priority: 1, - Actions: []ovs.Action{ - ovs.Resubmit(0, TLsToTun), - }, - }) - w.borders[name] = &OvsPort{ - name: name, - portId: port.PortID, - options: options, - } - // Update flow for flooding to border. - w.flood2Border() - } else { - _ = w.ovs.addFlow(&ovs.Flow{ - InPort: port.PortID, - Priority: 1, - Actions: []ovs.Action{ - ovs.Resubmit(0, TTunToLs), - }, - }) - w.tunnels[name] = &OvsPort{ - name: name, - portId: port.PortID, - options: options, - } - // Update flow for flooding to tunnels. - w.flood2Tunnel() - } -} - -func (w *FabricWorker) Start(v api.Switcher) { - w.out.Info("FabricWorker.Start") - for _, tunnel := range w.spec.Tunnels { - w.AddTunnel(*tunnel) - } - w.WorkerImpl.Start(v) - api.ListWorker(func(n api.Networker) { - if w.IsSlave(n) { - n.Start(v) - } - }) -} - -func (w *FabricWorker) downTables() { - _ = w.ovs.delFlow(nil) -} - -func (w *FabricWorker) DelNetwork(bridge string, vni uint32) { - brPort, tunPort := w.vni2peer(vni) - if err := w.ovs.delPort(tunPort); err != nil { - libol.Warn("FabricWorker.downNetwork %s", err) - } - link := &nl.Veth{ - LinkAttrs: nl.LinkAttrs{Name: tunPort}, - PeerName: brPort, - } - _ = nl.LinkDel(link) - if br, ok := w.bridge[bridge]; ok { - _ = br.Close() - } -} - -func (w *FabricWorker) DelTunnel(name string) { - _ = w.ovs.delPort(name) -} - -func (w *FabricWorker) IsSlave(n api.Networker) bool { - cfg := n.Config() - if cfg == nil || cfg.Specifies == nil { - return false - } - spec, ok := cfg.Specifies.(*co.VxLANSpecifies) - if !ok || spec.Fabric != w.cfg.Name { - return false - } - return true -} - -func (w *FabricWorker) Stop() { - w.out.Info("FabricWorker.Stop") - api.ListWorker(func(n api.Networker) { - if w.IsSlave(n) { - n.Stop() - } - }) - w.WorkerImpl.Stop() - w.downTables() - for _, tunnel := range w.tunnels { - w.DelTunnel(tunnel.name) - } -} - -func (w *FabricWorker) Reload(v api.Switcher) { - w.Stop() - w.Initialize() - w.Start(v) -} - -func (w *FabricWorker) TcpMss() int { - return w.cfg.Bridge.Mss -} diff --git a/pkg/switch/ipsec.go b/pkg/switch/ipsec.go new file mode 100644 index 0000000..d67994d --- /dev/null +++ b/pkg/switch/ipsec.go @@ -0,0 +1,230 @@ +package cswitch + +import ( + "fmt" + "os" + "text/template" + + "github.com/luscis/openlan/pkg/api" + co "github.com/luscis/openlan/pkg/config" + "github.com/luscis/openlan/pkg/libol" +) + +type IPSecWorker struct { + *WorkerImpl + spec *co.IPSecSpecifies +} + +func NewIPSecWorker(c *co.Network) *IPSecWorker { + w := &IPSecWorker{ + WorkerImpl: NewWorkerApi(c), + } + w.spec, _ = c.Specifies.(*co.IPSecSpecifies) + return w +} + +// conn vxlan11252 +// keyexchange=ike +// ikev2=no +// type=transport +// left=%defaultroute +// right=45.135.117.235 +// rightikeport=4501 +// authby=secret + +// conn vxlan11252-c2 +// auto=start +// also=vxlan11252 +// leftid=@c2.vxlan11252.com +// leftprotoport=udp/8472 +// rightprotoport=udp + +// conn vxlan11252-c1 +// auto=start +// also=vxlan11252 +// leftid=@c1.vxlan11252.com +// leftprotoport=udp +// rightprotoport=udp/8472 + +// conn vxlan11252 +// keyexchange=ike +// ikev2=no +// type=transport +// left=%defaultroute +// leftikeport=4501 +// right=218.94.118.90 +// authby=secret + +// conn vxlan11252-c1 +// auto=start +// also=vxlan11252 +// rightid=@c1.vxlan11252.com +// leftprotoport=udp/8472 +// rightprotoport=udp + +// conn vxlan11252-c2 +// auto=start +// also=vxlan11252 +// rightid=@c2.vxlan11252.com +// leftprotoport=udp +// rightprotoport=udp/8472 + +const ( + vxlanTmpl = ` +conn {{ .Name }} + keyexchange=ike + ikev2=no + type=transport + left={{ .Left }} +{{- if .LeftId }} + leftid={{ .LeftId }} +{{- end }} +{{- if .LeftPort }} + leftikeport={{ .LeftPort }} +{{- end }} + right={{ .Right }} +{{- if .RightId }} + rightid={{ .RightId }} +{{- end }} +{{- if .RightPort }} + rightikeport={{ .RightPort }} +{{- end }} + authby=secret + +conn {{ .Name }}-c1 + auto=start + also={{ .Name }} + leftprotoport=udp/8472 + rightprotoport=udp + +conn {{ .Name }}-c2 + auto=start + also={{ .Remote }}-{{ .Protocol }} + leftprotoport=udp + rightprotoport=udp/8472 +` + greTmpl = ` +conn {{ .Name }}-c1 + auto=start + ikev2=insist + type=transport + left={{ .Left }} + right={{ .Right }} + authby=secret + leftprotoport=gre + rightprotoport=gre +` + secretTmpl = ` +%any {{ .Remote }} : PSK "{{ .Secret }}" +` +) + +func (w *IPSecWorker) Initialize() { + w.out.Info("IPSecWorker.Initialize") +} + +func (w *IPSecWorker) saveSec(name, tmpl string, data interface{}) error { + file := fmt.Sprintf("/etc/ipsec.d/%s", name) + out, err := libol.CreateFile(file) + if err != nil || out == nil { + return err + } + defer out.Close() + if obj, err := template.New("main").Parse(tmpl); err != nil { + return err + } else { + if err := obj.Execute(out, data); err != nil { + return err + } + } + return nil +} + +func (w *IPSecWorker) startConn(name string) { + promise := libol.NewPromise() + promise.Go(func() error { + if out, err := libol.Exec("ipsec", "auto", "--start", "--asynchronous", name); err != nil { + w.out.Warn("IPSecWorker.startConn: %v %s", out, err) + return err + } + w.out.Info("IPSecWorker.startConn: %v success", name) + return nil + }) +} + +func (w *IPSecWorker) AddTunnel(tunnel *co.IPSecTunnel) error { + connTmpl := "" + secTmpl := "" + + name := fmt.Sprintf("%s-%s", tunnel.Right, tunnel.Transport) + if tunnel.Transport == "vxlan" { + connTmpl = vxlanTmpl + secTmpl = secretTmpl + } else if tunnel.Transport == "gre" { + connTmpl = greTmpl + secTmpl = secretTmpl + } + + if secTmpl != "" { + if err := w.saveSec(name+".secrets", secTmpl, tunnel); err != nil { + w.out.Error("WorkerImpl.AddTunnel %s", err) + return err + } + libol.Exec("ipsec", "auto", "--rereadsecrets") + } + if connTmpl != "" { + if err := w.saveSec(name+".conf", connTmpl, tunnel); err != nil { + w.out.Error("WorkerImpl.AddTunnel %s", err) + return err + } + if tunnel.Transport == "vxlan" { + w.startConn(name + "-c1") + w.startConn(name + "-c2") + } else if tunnel.Transport == "gre" { + w.startConn(name + "-c1") + } + } + + return nil +} + +func (w *IPSecWorker) Start(v api.Switcher) { + w.uuid = v.UUID() + w.out.Info("IPSecWorker.Start") +} + +func (w *IPSecWorker) RemoveTunnel(tunnel *co.IPSecTunnel) error { + + name := fmt.Sprintf("%s-%s", tunnel.Right, tunnel.Transport) + if tunnel.Transport == "vxlan" { + libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-c1") + libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-c2") + } else if tunnel.Transport == "gre" { + libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-c1") + } + + cfile := fmt.Sprintf("/etc/ipsec.d/%s.conf", name) + sfile := fmt.Sprintf("/etc/ipsec.d/%s.secrets", name) + + if err := libol.FileExist(cfile); err == nil { + if err := os.Remove(cfile); err != nil { + w.out.Warn("IPSecWorker.RemoveTunnel %s", err) + } + } + if err := libol.FileExist(sfile); err == nil { + if err := os.Remove(sfile); err != nil { + w.out.Warn("IPSecWorker.RemoveTunnel %s", err) + } + } + return nil +} + +func (w *IPSecWorker) Stop() { + w.out.Info("IPSecWorker.Stop") +} + +func (w *IPSecWorker) Reload(v api.Switcher) { + w.Stop() + w.Initialize() + w.Start(v) +} diff --git a/pkg/switch/network.go b/pkg/switch/network.go index 0ed5a39..8234358 100755 --- a/pkg/switch/network.go +++ b/pkg/switch/network.go @@ -3,9 +3,7 @@ package cswitch import ( "fmt" "net" - "os" "strings" - "text/template" "time" "github.com/luscis/openlan/pkg/api" @@ -21,8 +19,8 @@ import ( func NewNetworker(c *co.Network) api.Networker { var obj api.Networker switch c.Provider { - case "vxlan": - obj = NewVxLANWorker(c) + case "ipsec": + obj = NewIPSecWorker(c) case "router": obj = NewRouterWorker(c) default: @@ -185,12 +183,6 @@ func (w *WorkerImpl) AddPhysical(bridge string, output string) { } func (w *WorkerImpl) addOutput(bridge string, port *LinuxPort) { - if port.output.Secret != "" { - if err := w.addSecConn(port); err != nil { - w.out.Error("WorkerImpl.addOutput %s", err) - } - } - cfg := port.output mtu := 0 if cfg.Protocol == "gre" { @@ -469,12 +461,6 @@ func (w *WorkerImpl) DelPhysical(bridge string, output string) { } func (w *WorkerImpl) delOutput(bridge string, port *LinuxPort) { - if port.output.Secret != "" { - if err := w.delSecConn(port); err != nil { - w.out.Error("WorkerImpl.AddOutput %s", err) - } - } - cfg := port.output w.out.Info("WorkerImpl.delOutput %s %s", port.link, port.String()) @@ -558,11 +544,9 @@ func (w *WorkerImpl) Stop() { w.out.Info("WorkerImpl.Stop") w.fire.Stop() - w.nextgroup.Stop() w.unloadRoutes() - if !(w.vpn == nil) { if !(w.ztrust == nil) { w.ztrust.Stop() @@ -570,14 +554,14 @@ func (w *WorkerImpl) Stop() { if !(w.qos == nil) { w.qos.Stop() } - w.vpn.Stop() - } - if !(w.dhcp == nil) { w.dhcp.Stop() } + if !(w.vrf == nil) { + w.vrf.Down() + } for _, output := range w.outputs { w.delOutput(w.cfg.Bridge.Name, output) @@ -588,7 +572,6 @@ func (w *WorkerImpl) Stop() { w.setR.Destroy() w.setV.Destroy() - } func (w *WorkerImpl) String() string { @@ -1080,119 +1063,6 @@ func (w *WorkerImpl) ACLer() api.ACLer { return w.acl } -const ( - vxlanConn = ` -conn vxlan{{ .Segment }}-in - keyingtries=%forever - auto=start - ike=aes_gcm256-sha2_256 - esp=aes_gcm256 - ikev2=insist - type=transport - left=%defaultroute - right={{ .Remote }} - authby=secret - leftprotoport=udp/8472 - rightprotoport=udp - -conn vxlan{{ .Segment }}-out - keyingtries=%forever - auto=start - ike=aes_gcm256-sha2_256 - esp=aes_gcm256 - ikev2=insist - type=transport - left=%defaultroute - right={{ .Remote }} - authby=secret - leftprotoport=udp - rightprotoport=udp/8472 -` - greConn = ` -conn gre{{ .Segment }} - keyingtries=%forever - auto=start - ike=aes_gcm256-sha2_256 - esp=aes_gcm256 - ikev2=insist - type=transport - left=%defaultroute - right={{ .Remote }} - authby=secret - leftprotoport=gre - rightprotoport=gre -` - secretConn = ` -%any {{ .Remote }} : PSK "{{ .Secret }}" -` -) - -func (w *WorkerImpl) saveSec(name, tmpl string, data interface{}) error { - file := fmt.Sprintf("/etc/ipsec.d/%s", name) - out, err := libol.CreateFile(file) - if err != nil || out == nil { - return err - } - defer out.Close() - if obj, err := template.New("main").Parse(tmpl); err != nil { - return err - } else { - if err := obj.Execute(out, data); err != nil { - return err - } - } - return nil -} - -func (w *WorkerImpl) startSecConn(name string) { - promise := libol.NewPromise() - promise.Go(func() error { - if out, err := libol.Exec("ipsec", "auto", "--start", "--asynchronous", name); err != nil { - w.out.Warn("WorkerImpl.startSecConn: %v %s", out, err) - return err - } - w.out.Info("WorkerImpl.startSecConn: %v success", name) - return nil - }) -} - -func (w *WorkerImpl) addSecConn(port *LinuxPort) error { - connTmpl := "" - secTmpl := "" - - name := port.link - data := port.output - if data.Protocol == "vxlan" { - connTmpl = vxlanConn - secTmpl = secretConn - } else if data.Protocol == "gre" { - connTmpl = vxlanConn - secTmpl = secretConn - } - - if secTmpl != "" { - if err := w.saveSec(name+".secrets", secTmpl, data); err != nil { - w.out.Error("WorkerImpl.addSecConn %s", err) - return err - } - libol.Exec("ipsec", "auto", "--rereadsecrets") - } - if connTmpl != "" { - if err := w.saveSec(name+".conf", connTmpl, data); err != nil { - w.out.Error("WorkerImpl.addSecConn %s", err) - return err - } - if data.Protocol == "vxlan" { - w.startSecConn(name + "-in") - w.startSecConn(name + "-out") - } else if data.Protocol == "gre" { - w.startSecConn(name) - } - } - - return nil -} - func (w *WorkerImpl) AddOutput(data schema.Output) { output := co.Output{ Segment: data.Segment, @@ -1210,33 +1080,6 @@ func (w *WorkerImpl) AddOutput(data schema.Output) { w.outputs = append(w.outputs, port) } -func (w *WorkerImpl) delSecConn(port *LinuxPort) error { - data := port.output - name := port.link - - if data.Protocol == "vxlan" { - libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-in") - libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name+"-out") - } else if data.Protocol == "gre" { - libol.Exec("ipsec", "auto", "--delete", "--asynchronous", name) - } - - cfile := fmt.Sprintf("/etc/ipsec.d/%s.conf", name) - sfile := fmt.Sprintf("/etc/ipsec.d/%s.secrets", name) - - if err := libol.FileExist(cfile); err == nil { - if err := os.Remove(cfile); err != nil { - w.out.Warn("WorkerImpl.delSecConn %s", err) - } - } - if err := libol.FileExist(sfile); err == nil { - if err := os.Remove(sfile); err != nil { - w.out.Warn("WorkerImpl.delSecConn %s", err) - } - } - return nil -} - func (w *WorkerImpl) DelOutput(device string) { var port *LinuxPort for _, v := range w.outputs { diff --git a/pkg/switch/vxlan.go b/pkg/switch/vxlan.go deleted file mode 100755 index e27ef6b..0000000 --- a/pkg/switch/vxlan.go +++ /dev/null @@ -1,51 +0,0 @@ -package cswitch - -import ( - "github.com/luscis/openlan/pkg/api" - co "github.com/luscis/openlan/pkg/config" -) - -type VxLANWorker struct { - *WorkerImpl - spec *co.VxLANSpecifies -} - -func NewVxLANWorker(c *co.Network) *VxLANWorker { - w := &VxLANWorker{ - WorkerImpl: NewWorkerApi(c), - } - w.spec, _ = c.Specifies.(*co.VxLANSpecifies) - return w -} - -func (w *VxLANWorker) Initialize() { - w.WorkerImpl.Initialize() -} - -func (w *VxLANWorker) Start(v api.Switcher) { - w.uuid = v.UUID() - master := GetFabricer(w.spec.Fabric) - if master == nil { - w.out.Warn("VxLANWorker.Start %s not found", w.spec.Fabric) - return - } - w.cfg.Bridge.Mss = master.TcpMss() - master.AddNetwork(w.cfg) - w.WorkerImpl.Start(v) -} - -func (w *VxLANWorker) Stop() { - w.WorkerImpl.Stop() - master := GetFabricer(w.spec.Fabric) - if master == nil { - w.out.Warn("VxLANWorker.Stop %s not found", w.spec.Fabric) - return - } - master.DelNetwork(w.cfg.Bridge.Name, w.spec.Vni) -} - -func (w *VxLANWorker) Reload(v api.Switcher) { - w.Stop() - w.Initialize() - w.Start(v) -}