mirror of
https://github.com/luscis/openlan.git
synced 2025-12-24 11:10:54 +08:00
fea: cli for router tunnels.
This commit is contained in:
@@ -13,10 +13,43 @@ type Ceci struct {
|
||||
}
|
||||
|
||||
func (u Ceci) Url(prefix string) string {
|
||||
return prefix + "/api/network/ceci"
|
||||
}
|
||||
|
||||
func (u Ceci) List(c *cli.Context) error {
|
||||
url := u.Url(c.String("url"))
|
||||
clt := u.NewHttp(c.String("token"))
|
||||
var data schema.Network
|
||||
if err := clt.GetJSON(url, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.Out(data, "yaml", "")
|
||||
}
|
||||
|
||||
func (u Ceci) Commands(app *api.App) {
|
||||
app.Command(&cli.Command{
|
||||
Name: "ceci",
|
||||
Usage: "Ceci TCP proxy",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "ls",
|
||||
Usage: "List a ceci TCP",
|
||||
Action: u.List,
|
||||
},
|
||||
CeciTCP{}.Commands(app),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type CeciTCP struct {
|
||||
Cmd
|
||||
}
|
||||
|
||||
func (u CeciTCP) Url(prefix string) string {
|
||||
return prefix + "/api/network/ceci/tcp"
|
||||
}
|
||||
|
||||
func (u Ceci) Add(c *cli.Context) error {
|
||||
func (u CeciTCP) Add(c *cli.Context) error {
|
||||
target := strings.Split(c.String("target"), ",")
|
||||
data := &schema.CeciTcp{
|
||||
Mode: c.String("mode"),
|
||||
@@ -31,7 +64,7 @@ func (u Ceci) Add(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u Ceci) Remove(c *cli.Context) error {
|
||||
func (u CeciTCP) Remove(c *cli.Context) error {
|
||||
data := &schema.CeciTcp{
|
||||
Listen: c.String("listen"),
|
||||
}
|
||||
@@ -43,8 +76,8 @@ func (u Ceci) Remove(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u Ceci) Commands(app *api.App) {
|
||||
app.Command(&cli.Command{
|
||||
func (u CeciTCP) Commands(app *api.App) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "ceci",
|
||||
Usage: "Ceci TCP proxy",
|
||||
Subcommands: []*cli.Command{
|
||||
@@ -68,5 +101,5 @@ func (u Ceci) Commands(app *api.App) {
|
||||
Action: u.Remove,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,4 +43,5 @@ func Commands(app *api.App) {
|
||||
BGP{}.Commands(app)
|
||||
Ceci{}.Commands(app)
|
||||
Prefix{}.Commands(app)
|
||||
Router{}.Commands(app)
|
||||
}
|
||||
|
||||
@@ -10,12 +10,32 @@ type IPSec struct {
|
||||
Cmd
|
||||
}
|
||||
|
||||
func (o IPSec) Url(prefix string) string {
|
||||
return prefix + "/api/network/ipsec"
|
||||
}
|
||||
|
||||
func (o IPSec) List(c *cli.Context) error {
|
||||
url := o.Url(c.String("url"))
|
||||
clt := o.NewHttp(c.String("token"))
|
||||
var data schema.Network
|
||||
if err := clt.GetJSON(url, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
return o.Out(data, "yaml", "")
|
||||
}
|
||||
|
||||
func (o IPSec) Commands(app *api.App) {
|
||||
tunnel := IPSecTunnel{}
|
||||
app.Command(&cli.Command{
|
||||
Name: "ipsec",
|
||||
Usage: "IPSec configuration",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "ls",
|
||||
Usage: "Display ipsec network",
|
||||
Aliases: []string{"ls"},
|
||||
Action: o.List,
|
||||
},
|
||||
tunnel.Commands(),
|
||||
},
|
||||
})
|
||||
|
||||
109
cmd/api/v5/router.go
Normal file
109
cmd/api/v5/router.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package v5
|
||||
|
||||
import (
|
||||
"github.com/luscis/openlan/cmd/api"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// openlan router tunnel add --remote 1.1.1.2 --address 192.168.1.1 --protocol gre
|
||||
// openlan router tunnel add --remote 1.1.1.2 --address 192.168.1.1 --protocol ipip
|
||||
// openlan router tunnel remove --remote 1.1.1.2 --address 192.168.1.1
|
||||
|
||||
type Router struct {
|
||||
Cmd
|
||||
}
|
||||
|
||||
func (b Router) Url(prefix string) string {
|
||||
return prefix + "/api/network/router"
|
||||
}
|
||||
|
||||
func (b Router) List(c *cli.Context) error {
|
||||
url := b.Url(c.String("url"))
|
||||
clt := b.NewHttp(c.String("token"))
|
||||
var data schema.Network
|
||||
if err := clt.GetJSON(url, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
return b.Out(data, "yaml", "")
|
||||
}
|
||||
|
||||
func (b Router) Commands(app *api.App) {
|
||||
app.Command(&cli.Command{
|
||||
Name: "router",
|
||||
Usage: "Router",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "ls",
|
||||
Usage: "Display router network",
|
||||
Aliases: []string{"ls"},
|
||||
Action: b.List,
|
||||
},
|
||||
RouterTunnel{}.Commands(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type RouterTunnel struct {
|
||||
Cmd
|
||||
}
|
||||
|
||||
func (s RouterTunnel) Url(prefix string) string {
|
||||
return prefix + "/api/network/router/tunnel"
|
||||
}
|
||||
|
||||
func (s RouterTunnel) Add(c *cli.Context) error {
|
||||
data := &schema.RouterTunnel{
|
||||
Remote: c.String("remote"),
|
||||
Address: c.String("address"),
|
||||
Protocol: c.String("protocol"),
|
||||
}
|
||||
url := s.Url(c.String("url"))
|
||||
clt := s.NewHttp(c.String("token"))
|
||||
if err := clt.PostJSON(url, data, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s RouterTunnel) Remove(c *cli.Context) error {
|
||||
data := &schema.RouterTunnel{
|
||||
Remote: c.String("remote"),
|
||||
Protocol: c.String("protocol"),
|
||||
}
|
||||
url := s.Url(c.String("url"))
|
||||
clt := s.NewHttp(c.String("token"))
|
||||
if err := clt.DeleteJSON(url, data, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s RouterTunnel) Commands() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "tunnel",
|
||||
Usage: "Router tunnels",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Usage: "Add router tunnel",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "address", Required: true},
|
||||
&cli.StringFlag{Name: "remote", Required: true},
|
||||
&cli.StringFlag{Name: "protocol", Value: "gre"},
|
||||
},
|
||||
Action: s.Add,
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Aliases: []string{"rm"},
|
||||
Usage: "Remove router tunnel",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "remote", Required: true},
|
||||
&cli.StringFlag{Name: "protocol", Value: "gre"},
|
||||
},
|
||||
Action: s.Remove,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -156,11 +156,17 @@ type CeciApi interface {
|
||||
DelTcp(data schema.CeciTcp)
|
||||
}
|
||||
|
||||
type RouterApi interface {
|
||||
AddTunnel(data schema.RouterTunnel) error
|
||||
DelTunnel(data schema.RouterTunnel) error
|
||||
}
|
||||
|
||||
type callApi struct {
|
||||
ipsecApi IPSecApi
|
||||
bgpApi BgpApi
|
||||
ceciApi CeciApi
|
||||
workers map[string]NetworkApi
|
||||
ipsecApi IPSecApi
|
||||
bgpApi BgpApi
|
||||
ceciApi CeciApi
|
||||
routerApi RouterApi
|
||||
workers map[string]NetworkApi
|
||||
}
|
||||
|
||||
func (i *callApi) AddWorker(name string, obj NetworkApi) {
|
||||
@@ -189,6 +195,10 @@ func (i *callApi) SetCeciApi(value CeciApi) {
|
||||
i.ceciApi = value
|
||||
}
|
||||
|
||||
func (i *callApi) SetRouterApi(value RouterApi) {
|
||||
i.routerApi = value
|
||||
}
|
||||
|
||||
var Call = &callApi{
|
||||
workers: make(map[string]NetworkApi),
|
||||
}
|
||||
|
||||
@@ -232,3 +232,52 @@ func (h DNAT) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
ResponseJson(w, "success")
|
||||
}
|
||||
|
||||
type RouterTunnel struct {
|
||||
cs SwitchApi
|
||||
}
|
||||
|
||||
func (h RouterTunnel) Router(router *mux.Router) {
|
||||
router.HandleFunc("/api/network/router/tunnel", h.Post).Methods("POST")
|
||||
router.HandleFunc("/api/network/router/tunnel", h.Delete).Methods("DELETE")
|
||||
}
|
||||
|
||||
func (h RouterTunnel) Post(w http.ResponseWriter, r *http.Request) {
|
||||
caller := Call.routerApi
|
||||
if caller == nil {
|
||||
http.Error(w, "Router not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
value := schema.RouterTunnel{}
|
||||
if err := GetData(r, &value); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := caller.AddTunnel(value); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
ResponseJson(w, "success")
|
||||
}
|
||||
|
||||
func (h RouterTunnel) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
caller := Call.routerApi
|
||||
if caller == nil {
|
||||
http.Error(w, "Router not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
value := schema.RouterTunnel{}
|
||||
if err := GetData(r, &value); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := caller.DelTunnel(value); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
ResponseJson(w, "success")
|
||||
}
|
||||
|
||||
@@ -30,5 +30,6 @@ func Add(router *mux.Router, cs SwitchApi) {
|
||||
Rate{cs: cs}.Router(router)
|
||||
SNAT{}.Router(router)
|
||||
DNAT{}.Router(router)
|
||||
RouterTunnel{}.Router(router)
|
||||
Network{cs: cs}.Router(router)
|
||||
}
|
||||
|
||||
2
pkg/cache/network.go
vendored
2
pkg/cache/network.go
vendored
@@ -16,12 +16,10 @@ type network struct {
|
||||
}
|
||||
|
||||
func (w *network) Add(n *models.Network) {
|
||||
libol.Debug("network.Add %v", *n)
|
||||
_ = w.Networks.Set(n.Name, n)
|
||||
}
|
||||
|
||||
func (w *network) Del(name string) {
|
||||
libol.Debug("network.Del %s", name)
|
||||
w.Networks.Del(name)
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,14 @@ func (n *Network) NewSpecifies() any {
|
||||
case "bgp":
|
||||
n.Specifies = &BgpSpecifies{}
|
||||
case "ceci":
|
||||
|
||||
n.Specifies = &CeciSpecifies{}
|
||||
default:
|
||||
n.Specifies = nil
|
||||
}
|
||||
if n.Specifies != nil {
|
||||
n.Name = n.Provider
|
||||
}
|
||||
return n.Specifies
|
||||
}
|
||||
|
||||
|
||||
@@ -47,3 +47,30 @@ func (n *RouterSpecifies) Correct() {
|
||||
t.Correct()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *RouterSpecifies) FindTunnel(value *RouterTunnel) (*RouterTunnel, int) {
|
||||
for index, obj := range n.Tunnels {
|
||||
if obj.Id() == value.Id() {
|
||||
return obj, index
|
||||
}
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
func (n *RouterSpecifies) AddTunnel(value *RouterTunnel) bool {
|
||||
_, index := n.FindTunnel(value)
|
||||
if index == -1 {
|
||||
n.Tunnels = append(n.Tunnels, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *RouterSpecifies) DelTunnel(value *RouterTunnel) (*RouterTunnel, bool) {
|
||||
older, index := n.FindTunnel(value)
|
||||
if index != -1 {
|
||||
n.Tunnels = append(n.Tunnels[:index], n.Tunnels[index+1:]...)
|
||||
return older, true
|
||||
}
|
||||
return older, false
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ type Network struct {
|
||||
Name string `json:"name"`
|
||||
Tenant string `json:"tenant,omitempty"`
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
Address string `json:"address"`
|
||||
Address string `json:"address,omitempty"`
|
||||
IpStart string `json:"startAt,omitempty"`
|
||||
IpEnd string `json:"endAt,omitempty"`
|
||||
Netmask string `json:"netmask"`
|
||||
Netmask string `json:"netmask,omitempty"`
|
||||
Routes []*Route `json:"routes,omitempty"`
|
||||
Config interface{} `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
@@ -52,3 +52,9 @@ type DNAT struct {
|
||||
ToDest string `json:"todestination"`
|
||||
ToDport int `json:"todport"`
|
||||
}
|
||||
|
||||
type RouterTunnel struct {
|
||||
Protocol string `json:"protocol"`
|
||||
Remote string `json:"remote"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ func NewBgpWorker(c *co.Network) *BgpWorker {
|
||||
w := &BgpWorker{
|
||||
WorkerImpl: NewWorkerApi(c),
|
||||
}
|
||||
api.Call.SetBgpApi(w)
|
||||
w.spec, _ = c.Specifies.(*co.BgpSpecifies)
|
||||
return w
|
||||
}
|
||||
@@ -83,6 +84,7 @@ route-map {{ .Address }}-out permit 10
|
||||
|
||||
func (w *BgpWorker) Initialize() {
|
||||
w.out.Info("BgpWorker.Initialize")
|
||||
w.addCache()
|
||||
}
|
||||
|
||||
func (w *BgpWorker) save() {
|
||||
|
||||
@@ -24,12 +24,14 @@ func NewCeciWorker(c *co.Network) *CeciWorker {
|
||||
w := &CeciWorker{
|
||||
WorkerImpl: NewWorkerApi(c),
|
||||
}
|
||||
api.Call.SetCeciApi(w)
|
||||
w.spec, _ = c.Specifies.(*co.CeciSpecifies)
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *CeciWorker) Initialize() {
|
||||
w.out.Info("CeciWorker.Initialize")
|
||||
w.addCache()
|
||||
}
|
||||
|
||||
func (w *CeciWorker) killPid(name string) {
|
||||
|
||||
@@ -28,6 +28,8 @@ func NewIPSecWorker(c *co.Network) *IPSecWorker {
|
||||
w := &IPSecWorker{
|
||||
WorkerImpl: NewWorkerApi(c),
|
||||
}
|
||||
api.Call.SetIPSecApi(w)
|
||||
|
||||
w.spec, _ = c.Specifies.(*co.IPSecSpecifies)
|
||||
return w
|
||||
}
|
||||
@@ -102,6 +104,7 @@ func (w *IPSecWorker) Initialize() {
|
||||
if err := os.Mkdir(IPSecLogDir, 0600); err != nil {
|
||||
w.out.Warn("IPSecWorker.Initialize %s", err)
|
||||
}
|
||||
w.addCache()
|
||||
}
|
||||
|
||||
func (w *IPSecWorker) saveSec(name, tmpl string, data interface{}) error {
|
||||
|
||||
@@ -23,19 +23,13 @@ func NewNetworker(c *co.Network) api.NetworkApi {
|
||||
|
||||
switch c.Provider {
|
||||
case "ipsec":
|
||||
secer := NewIPSecWorker(c)
|
||||
api.Call.SetIPSecApi(secer)
|
||||
obj = secer
|
||||
obj = NewIPSecWorker(c)
|
||||
case "bgp":
|
||||
bgper := NewBgpWorker(c)
|
||||
api.Call.SetBgpApi(bgper)
|
||||
obj = bgper
|
||||
obj = NewBgpWorker(c)
|
||||
case "router":
|
||||
obj = NewRouterWorker(c)
|
||||
case "ceci":
|
||||
cecer := NewCeciWorker(c)
|
||||
api.Call.SetCeciApi(cecer)
|
||||
obj = cecer
|
||||
obj = NewCeciWorker(c)
|
||||
default:
|
||||
obj = NewOpenLANWorker(c)
|
||||
}
|
||||
@@ -85,6 +79,21 @@ func (w *WorkerImpl) Provider() string {
|
||||
return w.cfg.Provider
|
||||
}
|
||||
|
||||
func (w *WorkerImpl) addCache() {
|
||||
cfg := w.cfg
|
||||
n := models.Network{
|
||||
Name: cfg.Name,
|
||||
Config: cfg,
|
||||
}
|
||||
if cfg.Subnet != nil {
|
||||
n.IpStart = cfg.Subnet.Start
|
||||
n.IpEnd = cfg.Subnet.End
|
||||
n.Netmask = cfg.Subnet.Netmask
|
||||
n.Address = cfg.Bridge.Address
|
||||
}
|
||||
cache.Network.Add(&n)
|
||||
}
|
||||
|
||||
func (w *WorkerImpl) Initialize() {
|
||||
cfg := w.cfg
|
||||
|
||||
@@ -96,18 +105,8 @@ func (w *WorkerImpl) Initialize() {
|
||||
w.acl = NewACL(cfg.Name)
|
||||
w.acl.Initialize()
|
||||
|
||||
w.addCache()
|
||||
w.findhop = NewFindHop(cfg.Name, cfg)
|
||||
if cfg.Subnet != nil {
|
||||
n := models.Network{
|
||||
Name: cfg.Name,
|
||||
IpStart: cfg.Subnet.Start,
|
||||
IpEnd: cfg.Subnet.End,
|
||||
Netmask: cfg.Subnet.Netmask,
|
||||
Address: cfg.Bridge.Address,
|
||||
Config: cfg,
|
||||
}
|
||||
cache.Network.Add(&n)
|
||||
}
|
||||
|
||||
w.updateVPN()
|
||||
w.createVPN()
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/luscis/openlan/pkg/api"
|
||||
co "github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
nl "github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,7 @@ func NewRouterWorker(c *co.Network) *RouterWorker {
|
||||
w := &RouterWorker{
|
||||
WorkerImpl: NewWorkerApi(c),
|
||||
}
|
||||
api.Call.SetRouterApi(w)
|
||||
w.spec, _ = c.Specifies.(*co.RouterSpecifies)
|
||||
return w
|
||||
}
|
||||
@@ -74,7 +76,7 @@ func (w *RouterWorker) Start(v api.SwitchApi) {
|
||||
w.uuid = v.UUID()
|
||||
|
||||
for _, tun := range w.spec.Tunnels {
|
||||
w.AddTunnel(tun)
|
||||
w.addTunnel(tun)
|
||||
}
|
||||
|
||||
w.WorkerImpl.Start(v)
|
||||
@@ -102,7 +104,7 @@ func (w *RouterWorker) Stop() {
|
||||
w.WorkerImpl.Stop()
|
||||
|
||||
for _, tun := range w.spec.Tunnels {
|
||||
w.DelTunnel(tun)
|
||||
w.delTunnel(tun)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +114,7 @@ func (w *RouterWorker) Reload(v api.SwitchApi) {
|
||||
w.Start(v)
|
||||
}
|
||||
|
||||
func (w *RouterWorker) AddTunnel(data *co.RouterTunnel) {
|
||||
func (w *RouterWorker) addTunnel(data *co.RouterTunnel) {
|
||||
var link nl.Link
|
||||
|
||||
switch data.Protocol {
|
||||
@@ -159,14 +161,38 @@ func (w *RouterWorker) AddTunnel(data *co.RouterTunnel) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *RouterWorker) DelTunnel(data *co.RouterTunnel) {
|
||||
if data.Link == "" {
|
||||
return
|
||||
}
|
||||
func (w *RouterWorker) delTunnel(data *co.RouterTunnel) {
|
||||
if link, err := nl.LinkByName(data.Link); err == nil {
|
||||
if err := nl.LinkDel(link); err != nil {
|
||||
w.out.Error("RouterWorker.DelTunnel %s %s", data.Id(), err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
w.out.Warn("RouterWorker.DelTunnel notFound %s:%s", data.Id(), data.Link)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *RouterWorker) AddTunnel(data schema.RouterTunnel) error {
|
||||
obj := &co.RouterTunnel{
|
||||
Remote: data.Remote,
|
||||
Protocol: data.Protocol,
|
||||
Address: data.Address,
|
||||
}
|
||||
obj.Correct()
|
||||
if ok := w.spec.AddTunnel(obj); ok {
|
||||
w.addTunnel(obj)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *RouterWorker) DelTunnel(data schema.RouterTunnel) error {
|
||||
obj := &co.RouterTunnel{
|
||||
Remote: data.Remote,
|
||||
Protocol: data.Protocol,
|
||||
}
|
||||
obj.Correct()
|
||||
if old, ok := w.spec.DelTunnel(obj); ok {
|
||||
w.delTunnel(old)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user