fea: switch: do dnat.
Some checks failed
Coverage CI / build (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
Ubuntu CI / build (push) Has been cancelled

This commit is contained in:
Daniel Ding
2025-10-22 10:48:56 +08:00
parent eb9a1acc1c
commit caef90cc04
24 changed files with 382 additions and 175 deletions

View File

@@ -196,14 +196,16 @@ func (s SNAT) Commands() *cli.Command {
Usage: "Configure SNAT",
Subcommands: []*cli.Command{
{
Name: "enable",
Usage: "Enable snat",
Action: s.Enable,
Name: "enable",
Usage: "Enable snat",
Aliases: []string{"en"},
Action: s.Enable,
},
{
Name: "disable",
Usage: "Disable snat",
Action: s.Disable,
Name: "disable",
Usage: "Disable snat",
Aliases: []string{"dis"},
Action: s.Disable,
},
},
}
@@ -251,16 +253,35 @@ func (s DNAT) Delete(c *cli.Context) error {
return nil
}
func (s DNAT) List(c *cli.Context) error {
url := s.Url(c.String("url"), c.String("name"))
clt := s.NewHttp(c.String("token"))
var items []schema.DNAT
if err := clt.GetJSON(url, &items); err == nil {
return s.Out(items, c.String("format"), "")
} else {
return err
}
}
func (s DNAT) Commands() *cli.Command {
return &cli.Command{
Name: "dnat",
Usage: "Configure DNAT",
Subcommands: []*cli.Command{
{
Name: "list",
Usage: "Liat all dnat",
Aliases: []string{"ls"},
Action: s.List,
},
{
Name: "add",
Usage: "Add a dnat",
Flags: []cli.Flag{
&cli.StringFlag{Name: "protocol", Required: true},
&cli.StringFlag{Name: "protocol", Value: "tcp"},
&cli.IntFlag{Name: "dport", Required: true},
&cli.StringFlag{Name: "dest", Required: true},
&cli.StringFlag{Name: "todest", Required: true},
@@ -269,14 +290,13 @@ func (s DNAT) Commands() *cli.Command {
Action: s.Add,
},
{
Name: "remove",
Usage: "Remove a snat",
Name: "remove",
Usage: "Remove a snat",
Aliases: []string{"rm"},
Flags: []cli.Flag{
&cli.StringFlag{Name: "protocol", Required: true},
&cli.StringFlag{Name: "protocol", Value: "tcp"},
&cli.IntFlag{Name: "dport", Required: true},
&cli.StringFlag{Name: "dest", Required: true},
&cli.StringFlag{Name: "todest", Required: true},
&cli.IntFlag{Name: "todport", Required: true},
},
Action: s.Delete,
},

View File

@@ -8,7 +8,7 @@ import (
)
type ACL struct {
Switcher Switcher
SwitchApi SwitchApi
}
func (h ACL) Router(router *mux.Router) {

View File

@@ -9,12 +9,12 @@ import (
"github.com/luscis/openlan/pkg/schema"
)
type Rater interface {
type RateApi interface {
AddRate(device string, mbit int)
DelRate(device string)
}
type Switcher interface {
type SwitchApi interface {
UUID() string
UpTime() int64
Alias() string
@@ -25,10 +25,10 @@ type Switcher interface {
AddNetwork(network string)
DelNetwork(network string)
SaveNetwork(network string)
Rater
RateApi
}
func NewWorkerSchema(s Switcher) schema.Worker {
func NewWorkerSchema(s SwitchApi) schema.Worker {
protocol := ""
if cfg := s.Config(); cfg != nil {
protocol = cfg.Protocol
@@ -41,14 +41,14 @@ func NewWorkerSchema(s Switcher) schema.Worker {
}
}
type ACLer interface {
type ACLApi interface {
AddRule(rule *schema.ACLRule) error
DelRule(rule *schema.ACLRule) error
ListRules(call func(obj schema.ACLRule))
SaveRule()
}
type ZTruster interface {
type ZTrustApi interface {
AddGuest(name, source string) error
DelGuest(name, source string) error
Knock(name string, protocol, dest, port string, age int) error
@@ -56,21 +56,21 @@ type ZTruster interface {
ListKnock(name string, call func(obj schema.KnockRule))
}
type Router interface {
AddRoute(route *schema.PrefixRoute, switcher Switcher) error
DelRoute(route *schema.PrefixRoute, switcher Switcher) error
type RouteApi interface {
AddRoute(route *schema.PrefixRoute, switchApi SwitchApi) error
DelRoute(route *schema.PrefixRoute, switchApi SwitchApi) error
ListRoute(call func(obj schema.PrefixRoute))
SaveRoute()
}
type VPNer interface {
type VPNApi interface {
StartVPN()
AddVPNClient(name, local string) error
DelVPNClient(name string) error
ListClients(call func(name, local string))
}
type Qoser interface {
type QosApi interface {
AddQos(name string, inSpeed float64) error
UpdateQos(name string, inSpeed float64) error
DelQos(name string) error
@@ -78,57 +78,68 @@ type Qoser interface {
SaveQos()
}
type Outputer interface {
type OutputApi interface {
AddOutput(data schema.Output)
DelOutput(data schema.Output)
SaveOutput()
}
type FindHoper interface {
type FindHopApi interface {
AddHop(data schema.FindHop) error
DelHop(data schema.FindHop) error
ListHop(call func(obj schema.FindHop))
SaveHop()
}
type Super interface {
type SNATApi interface {
EnableSnat()
DisableSnat()
}
type DNATApi interface {
AddDnat(data schema.DNAT) error
DelDnat(data schema.DNAT) error
ListDnat(call func(obj schema.DNAT))
}
type SupeApi interface {
String() string
ID() string
Initialize()
Start(v Switcher)
Start(v SwitchApi)
Stop()
Reload(v Switcher)
Reload(v SwitchApi)
}
type Networker interface {
Super
type NetworkApi interface {
SupeApi
Config() *co.Network
Subnet() *net.IPNet
Provider() string
IfAddr() string
SetMss(mss int)
Outputer
Router
VPNer
OutputApi
RouteApi
VPNApi
Bridger() cn.Bridger
ZTruster() ZTruster
Qoser() Qoser
ACLer() ACLer
FindHoper() FindHoper
ZTruster() ZTrustApi
Qoser() QosApi
ACLer() ACLApi
FindHoper() FindHopApi
EnableZTrust()
DisableZTrust()
EnableSnat()
DisableSnat()
SNATApi
DNATApi
}
type IPSecer interface {
type IPSecApi interface {
AddTunnel(data schema.IPSecTunnel)
DelTunnel(data schema.IPSecTunnel)
StartTunnel(data schema.IPSecTunnel)
ListTunnels(call func(obj schema.IPSecTunnel))
}
type Bgper interface {
type BgpApi interface {
Enable(data schema.Bgp)
Disable()
Get() *schema.Bgp
@@ -140,42 +151,34 @@ type Bgper interface {
DelAdvertis(data schema.BgpPrefix)
}
type APICall struct {
secer IPSecer
bgper Bgper
workers map[string]Networker
type callApi struct {
ipsecApi IPSecApi
bgpApi BgpApi
workers map[string]NetworkApi
}
func (i *APICall) AddWorker(name string, obj Networker) {
func (i *callApi) AddWorker(name string, obj NetworkApi) {
i.workers[name] = obj
}
func (i *APICall) GetWorker(name string) Networker {
func (i *callApi) GetWorker(name string) NetworkApi {
return i.workers[name]
}
func (i *APICall) ListWorker(call func(w Networker)) {
for _, worker := range i.workers {
call(worker)
func (i *callApi) ListWorker(call func(w NetworkApi)) {
for _, w := range i.workers {
call(w)
}
}
func (i *APICall) SetIPSecer(value IPSecer) {
i.secer = value
func (i *callApi) SetIPSecer(value IPSecApi) {
i.ipsecApi = value
}
func (i *APICall) GetIPSecer() IPSecer {
return i.secer
func (i *callApi) SetBgper(value BgpApi) {
i.bgpApi = value
}
func (i *APICall) SetBgper(value Bgper) {
i.bgper = value
}
func (i *APICall) GetBgper() Bgper {
return i.bgper
}
var Call = &APICall{
workers: make(map[string]Networker),
var Call = &callApi{
workers: make(map[string]NetworkApi),
}

View File

@@ -9,7 +9,7 @@ import (
)
type Bgp struct {
Switcher Switcher
cs SwitchApi
}
func (h Bgp) Router(router *mux.Router) {
@@ -26,11 +26,11 @@ func (h Bgp) Router(router *mux.Router) {
func (h Bgp) Get(w http.ResponseWriter, r *http.Request) {
libol.Debug("Bgp.Get %s")
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
data := Call.bgper.Get()
data := Call.bgpApi.Get()
ResponseJson(w, data)
}
@@ -40,20 +40,20 @@ func (h Bgp) Post(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.Enable(data)
Call.bgpApi.Enable(data)
ResponseMsg(w, 0, "")
}
func (h Bgp) Remove(w http.ResponseWriter, r *http.Request) {
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.Disable()
Call.bgpApi.Disable()
ResponseMsg(w, 0, "")
}
@@ -63,11 +63,11 @@ func (h Bgp) RemoveNeighbor(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.DelNeighbor(nei)
Call.bgpApi.DelNeighbor(nei)
ResponseMsg(w, 0, "")
}
@@ -77,11 +77,11 @@ func (h Bgp) AddNeighbor(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.AddNeighbor(nei)
Call.bgpApi.AddNeighbor(nei)
ResponseMsg(w, 0, "")
}
@@ -91,11 +91,11 @@ func (h Bgp) RemoveAdvertis(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.DelAdvertis(data)
Call.bgpApi.DelAdvertis(data)
ResponseMsg(w, 0, "")
}
@@ -105,11 +105,11 @@ func (h Bgp) AddAdvertis(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.AddAdvertis(data)
Call.bgpApi.AddAdvertis(data)
ResponseMsg(w, 0, "")
}
@@ -119,11 +119,11 @@ func (h Bgp) RemoveReceivess(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.DelReceives(data)
Call.bgpApi.DelReceives(data)
ResponseMsg(w, 0, "")
}
@@ -133,10 +133,10 @@ func (h Bgp) AddReceivess(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.bgper == nil {
if Call.bgpApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.bgper.AddReceives(data)
Call.bgpApi.AddReceives(data)
ResponseMsg(w, 0, "")
}

View File

@@ -1,12 +1,13 @@
package api
import (
"github.com/gorilla/mux"
"net/http"
"github.com/gorilla/mux"
)
type Config struct {
Switcher Switcher
cs SwitchApi
}
func (c Config) Router(router *mux.Router) {
@@ -18,18 +19,18 @@ func (c Config) Router(router *mux.Router) {
func (c Config) List(w http.ResponseWriter, r *http.Request) {
format := GetQueryOne(r, "format")
if format == "yaml" {
ResponseYaml(w, c.Switcher.Config())
ResponseYaml(w, c.cs.Config())
} else {
ResponseJson(w, c.Switcher.Config())
ResponseJson(w, c.cs.Config())
}
}
func (c Config) Reload(w http.ResponseWriter, r *http.Request) {
c.Switcher.Reload()
c.cs.Reload()
ResponseMsg(w, 0, "success")
}
func (c Config) Save(w http.ResponseWriter, r *http.Request) {
c.Switcher.Save()
c.cs.Save()
ResponseMsg(w, 0, "success")
}

View File

@@ -8,7 +8,7 @@ import (
)
type FindHop struct {
Switcher Switcher
cs SwitchApi
}
func (rt FindHop) Router(router *mux.Router) {

View File

@@ -9,7 +9,7 @@ import (
)
type IPSec struct {
Switcher Switcher
cs SwitchApi
}
func (h IPSec) Router(router *mux.Router) {
@@ -22,11 +22,11 @@ func (h IPSec) Router(router *mux.Router) {
func (h IPSec) Get(w http.ResponseWriter, r *http.Request) {
libol.Debug("IPSec.Get %s")
tunnels := make([]schema.IPSecTunnel, 0, 1024)
if Call.secer == nil {
if Call.ipsecApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.secer.ListTunnels(func(obj schema.IPSecTunnel) {
Call.ipsecApi.ListTunnels(func(obj schema.IPSecTunnel) {
tunnels = append(tunnels, obj)
})
ResponseJson(w, tunnels)
@@ -38,11 +38,11 @@ func (h IPSec) Post(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.secer == nil {
if Call.ipsecApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.secer.AddTunnel(*tun)
Call.ipsecApi.AddTunnel(*tun)
ResponseMsg(w, 0, "")
}
@@ -52,11 +52,11 @@ func (h IPSec) Delete(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.secer == nil {
if Call.ipsecApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.secer.DelTunnel(*tun)
Call.ipsecApi.DelTunnel(*tun)
ResponseMsg(w, 0, "")
}
@@ -66,10 +66,10 @@ func (h IPSec) Start(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if Call.secer == nil {
if Call.ipsecApi == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
}
Call.secer.StartTunnel(*tun)
Call.ipsecApi.StartTunnel(*tun)
ResponseMsg(w, 0, "")
}

View File

@@ -11,7 +11,7 @@ import (
)
type Link struct {
Switcher Switcher
cs SwitchApi
}
func (h Link) Router(router *mux.Router) {

View File

@@ -12,7 +12,7 @@ import (
)
type Network struct {
Switcher Switcher
cs SwitchApi
}
func (h Network) Router(router *mux.Router) {
@@ -23,7 +23,7 @@ func (h Network) Router(router *mux.Router) {
router.HandleFunc("/api/network/{id}", h.Delete).Methods("DELETE")
router.HandleFunc("/get/network/{id}/ovpn", h.Profile).Methods("GET")
router.HandleFunc("/api/network/{id}/ovpn", h.Profile).Methods("GET")
router.HandleFunc("/api/network/{id}/openvpn/restart", h.RestartVPN).Methods("POST")
router.HandleFunc("/api/network/{id}/openvpn/restart", h.StartVPN).Methods("POST")
}
func (h Network) List(w http.ResponseWriter, r *http.Request) {
@@ -58,7 +58,7 @@ func (h Network) Post(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
cs := h.Switcher.Config()
cs := h.cs.Config()
obj, err := cs.AddNetwork(data)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
@@ -67,7 +67,7 @@ func (h Network) Post(w http.ResponseWriter, r *http.Request) {
cs.CorrectNetwork(obj, "json")
if obj := cs.GetNetwork(obj.Name); obj != nil {
h.Switcher.AddNetwork(obj.Name)
h.cs.AddNetwork(obj.Name)
} else {
http.Error(w, obj.Name+" not found", http.StatusBadRequest)
return
@@ -84,7 +84,7 @@ func (h Network) Delete(w http.ResponseWriter, r *http.Request) {
http.Error(w, "network not found", http.StatusBadRequest)
return
}
h.Switcher.DelNetwork(network)
h.cs.DelNetwork(network)
ResponseJson(w, "success")
}
@@ -94,7 +94,7 @@ func (h Network) Save(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
h.Switcher.SaveNetwork(network.Name)
h.cs.SaveNetwork(network.Name)
ResponseJson(w, "success")
}
@@ -109,7 +109,7 @@ func (h Network) Profile(w http.ResponseWriter, r *http.Request) {
}
}
func (h Network) RestartVPN(w http.ResponseWriter, r *http.Request) {
func (h Network) StartVPN(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
@@ -124,7 +124,7 @@ func (h Network) RestartVPN(w http.ResponseWriter, r *http.Request) {
}
type SNAT struct {
Switcher Switcher
cs SwitchApi
}
func (h SNAT) Router(router *mux.Router) {
@@ -159,3 +159,76 @@ func (h SNAT) Delete(w http.ResponseWriter, r *http.Request) {
ResponseJson(w, "success")
}
type DNAT struct {
cs SwitchApi
}
func (h DNAT) Router(router *mux.Router) {
router.HandleFunc("/api/network/{id}/dnat", h.Get).Methods("GET")
router.HandleFunc("/api/network/{id}/dnat", h.Post).Methods("POST")
router.HandleFunc("/api/network/{id}/dnat", h.Delete).Methods("DELETE")
}
func (h DNAT) Get(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["id"]
caller := Call.GetWorker(name)
if caller == nil {
http.Error(w, name+" not found", http.StatusBadRequest)
return
}
var items []schema.DNAT
caller.ListDnat(func(data schema.DNAT) {
items = append(items, data)
})
ResponseJson(w, items)
}
func (h DNAT) Post(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["id"]
caller := Call.GetWorker(name)
if caller == nil {
http.Error(w, name+" not found", http.StatusBadRequest)
return
}
value := schema.DNAT{}
if err := GetData(r, &value); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := caller.AddDnat(value); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ResponseJson(w, "success")
}
func (h DNAT) Delete(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["id"]
caller := Call.GetWorker(name)
if caller == nil {
http.Error(w, name+" not found", http.StatusBadRequest)
return
}
value := schema.DNAT{}
if err := GetData(r, &value); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := caller.DelDnat(value); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ResponseJson(w, "success")
}

View File

@@ -11,7 +11,7 @@ import (
)
type Output struct {
Switcher Switcher
cs SwitchApi
}
func (h Output) Router(router *mux.Router) {
@@ -45,7 +45,7 @@ func (h Output) Post(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
cs := h.Switcher.Config()
cs := h.cs.Config()
if cs.Network[name] == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return
@@ -68,7 +68,7 @@ func (h Output) Delete(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
cs := h.Switcher.Config()
cs := h.cs.Config()
if cs.Network[name] == nil {
http.Error(w, "network is nil", http.StatusBadRequest)
return

View File

@@ -7,17 +7,17 @@ import (
"github.com/luscis/openlan/pkg/schema"
)
type QosApi struct {
type Qos struct {
}
func (h QosApi) Router(router *mux.Router) {
func (h Qos) Router(router *mux.Router) {
router.HandleFunc("/api/network/{id}/qos", h.List).Methods("GET")
router.HandleFunc("/api/network/{id}/qos", h.Add).Methods("POST")
router.HandleFunc("/api/network/{id}/qos", h.Del).Methods("DELETE")
router.HandleFunc("/api/network/{id}/qos", h.Save).Methods("PUT")
}
func (h QosApi) List(w http.ResponseWriter, r *http.Request) {
func (h Qos) List(w http.ResponseWriter, r *http.Request) {
qosList := make([]schema.Qos, 0, 1024)
vars := mux.Vars(r)
@@ -37,7 +37,7 @@ func (h QosApi) List(w http.ResponseWriter, r *http.Request) {
ResponseJson(w, qosList)
}
func (h QosApi) Add(w http.ResponseWriter, r *http.Request) {
func (h Qos) Add(w http.ResponseWriter, r *http.Request) {
qos := &schema.Qos{}
if err := GetData(r, qos); err != nil {
@@ -65,7 +65,7 @@ func (h QosApi) Add(w http.ResponseWriter, r *http.Request) {
}
}
func (h QosApi) Del(w http.ResponseWriter, r *http.Request) {
func (h Qos) Del(w http.ResponseWriter, r *http.Request) {
qos := &schema.Qos{}
if err := GetData(r, qos); err != nil {
@@ -93,7 +93,7 @@ func (h QosApi) Del(w http.ResponseWriter, r *http.Request) {
}
}
func (h QosApi) Save(w http.ResponseWriter, r *http.Request) {
func (h Qos) Save(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]

View File

@@ -8,7 +8,7 @@ import (
)
type Rate struct {
Switcher Switcher
cs SwitchApi
}
func (h Rate) Router(router *mux.Router) {
@@ -25,11 +25,11 @@ func (h Rate) Post(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
h.Switcher.AddRate(device, rate.Speed)
h.cs.AddRate(device, rate.Speed)
}
func (h Rate) Delete(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
device := vars["id"]
h.Switcher.DelRate(device)
h.cs.DelRate(device)
}

View File

@@ -8,7 +8,7 @@ import (
)
type Route struct {
Switcher Switcher
cs SwitchApi
}
func (rt Route) Router(router *mux.Router) {
@@ -52,7 +52,7 @@ func (rt Route) Add(w http.ResponseWriter, r *http.Request) {
return
}
if err := worker.AddRoute(pr, rt.Switcher); err != nil {
if err := worker.AddRoute(pr, rt.cs); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
@@ -76,7 +76,7 @@ func (rt Route) Del(w http.ResponseWriter, r *http.Request) {
return
}
if err := worker.DelRoute(pr, rt.Switcher); err != nil {
if err := worker.DelRoute(pr, rt.cs); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

View File

@@ -1,12 +1,13 @@
package api
import (
"github.com/gorilla/mux"
"net/http"
"github.com/gorilla/mux"
)
type Server struct {
Switcher Switcher
cs SwitchApi
}
func (l Server) Router(router *mux.Router) {
@@ -15,14 +16,14 @@ func (l Server) Router(router *mux.Router) {
}
func (l Server) List(w http.ResponseWriter, r *http.Request) {
server := l.Switcher.Server()
server := l.cs.Server()
data := &struct {
UpTime int64 `json:"uptime"`
Total int `json:"total"`
Statistic map[string]int64 `json:"statistic"`
Connection []interface{} `json:"connection"`
}{
UpTime: l.Switcher.UpTime(),
UpTime: l.cs.UpTime(),
Statistic: server.Statistics(),
Connection: make([]interface{}, 0, 1024),
Total: server.TotalClient(),

View File

@@ -2,8 +2,8 @@ package api
import "github.com/gorilla/mux"
func Add(router *mux.Router, switcher Switcher) {
Link{Switcher: switcher}.Router(router)
func Add(router *mux.Router, cs SwitchApi) {
Link{cs: cs}.Router(router)
User{}.Router(router)
Bgp{}.Router(router)
IPSec{}.Router(router)
@@ -12,21 +12,22 @@ func Add(router *mux.Router, switcher Switcher) {
Access{}.Router(router)
OnLine{}.Router(router)
Lease{}.Router(router)
Server{Switcher: switcher}.Router(router)
Server{cs: cs}.Router(router)
Device{}.Router(router)
VPNClient{}.Router(router)
PProf{}.Router(router)
Config{Switcher: switcher}.Router(router)
Config{cs: cs}.Router(router)
Version{}.Router(router)
Log{}.Router(router)
OpenAPI{}.Router(router)
ZTrust{}.Router(router)
QosApi{}.Router(router)
Output{Switcher: switcher}.Router(router)
Qos{}.Router(router)
Output{cs: cs}.Router(router)
ACL{}.Router(router)
Route{Switcher: switcher}.Router(router)
Route{cs: cs}.Router(router)
FindHop{}.Router(router)
Rate{Switcher: switcher}.Router(router)
Rate{cs: cs}.Router(router)
SNAT{}.Router(router)
Network{Switcher: switcher}.Router(router)
DNAT{}.Router(router)
Network{cs: cs}.Router(router)
}

View File

@@ -11,7 +11,7 @@ import (
)
type ZTrust struct {
Switcher Switcher
cs SwitchApi
}
func (h ZTrust) Router(router *mux.Router) {

View File

@@ -180,12 +180,16 @@ func (n *Network) LoadDnat() {
func (n *Network) Save() {
obj := *n
obj.Routes = nil
obj.Links = nil
obj.Outputs = nil
obj.Dnat = nil
obj.FindHop = nil
if err := libol.MarshalSave(&obj, obj.File, true); err != nil {
libol.Error("Network.Save %s %s", obj.Name, err)
}
n.SaveRoute()
n.SaveLink()
n.SaveOutput()
@@ -341,3 +345,9 @@ func (n *Network) DelDnat(value *Dnat) (*Dnat, bool) {
}
return older, false
}
func (n *Network) ListDnat(call func(value Dnat)) {
for _, obj := range n.Dnat {
call(*obj)
}
}

View File

@@ -116,7 +116,7 @@ func (w *BgpWorker) reload() {
}
}
func (w *BgpWorker) Start(v api.Switcher) {
func (w *BgpWorker) Start(v api.SwitchApi) {
w.uuid = v.UUID()
w.out.Info("BgpWorker.Start")
w.reload()
@@ -172,7 +172,7 @@ func (w *BgpWorker) Get() *schema.Bgp {
return data
}
func (w *BgpWorker) Reload(v api.Switcher) {
func (w *BgpWorker) Reload(v api.SwitchApi) {
w.Stop()
w.Initialize()
w.Start(v)

View File

@@ -31,7 +31,7 @@ func NotAllowed(w http.ResponseWriter, r *http.Request) {
}
type Http struct {
switcher api.Switcher
cs api.SwitchApi
listen string
adminToken string
adminFile string
@@ -42,10 +42,10 @@ type Http struct {
router *mux.Router
}
func NewHttp(switcher api.Switcher) (h *Http) {
func NewHttp(cs api.SwitchApi) (h *Http) {
c := co.Get()
h = &Http{
switcher: switcher,
cs: cs,
listen: c.Http.Listen,
adminFile: c.TokenFile,
pubDir: c.Http.Public,
@@ -136,7 +136,7 @@ func (h *Http) LoadRouter() {
h.Prome(router)
router.HandleFunc("/api/index", h.GetIndex).Methods("GET")
router.HandleFunc("/api/urls", h.GetApi).Methods("GET")
api.Add(router, h.switcher)
api.Add(router, h.cs)
}
func (h *Http) LoadToken() {
@@ -244,7 +244,7 @@ func (h *Http) PubFile(w http.ResponseWriter, r *http.Request) {
func (h *Http) getIndex(body *schema.Index) *schema.Index {
body.Version = schema.NewVersionSchema()
body.Worker = api.NewWorkerSchema(h.switcher)
body.Worker = api.NewWorkerSchema(h.cs)
// display accessed Access.
for p := range cache.Access.List() {

View File

@@ -184,7 +184,7 @@ func (w *IPSecWorker) addTunnel(tun *co.IPSecTunnel) error {
return nil
}
func (w *IPSecWorker) Start(v api.Switcher) {
func (w *IPSecWorker) Start(v api.SwitchApi) {
w.uuid = v.UUID()
w.out.Info("IPSecWorker.Start")
for _, tun := range w.spec.Tunnels {
@@ -261,7 +261,7 @@ func (w *IPSecWorker) Stop() {
}
}
func (w *IPSecWorker) Reload(v api.Switcher) {
func (w *IPSecWorker) Reload(v api.SwitchApi) {
w.Stop()
w.Initialize()
w.Start(v)

View File

@@ -9,6 +9,7 @@ import (
"github.com/luscis/openlan/pkg/api"
"github.com/luscis/openlan/pkg/cache"
"github.com/luscis/openlan/pkg/config"
co "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol"
"github.com/luscis/openlan/pkg/models"
@@ -17,8 +18,9 @@ import (
nl "github.com/vishvananda/netlink"
)
func NewNetworker(c *co.Network) api.Networker {
var obj api.Networker
func NewNetworker(c *co.Network) api.NetworkApi {
var obj api.NetworkApi
switch c.Provider {
case "ipsec":
secer := NewIPSecWorker(c)
@@ -62,6 +64,7 @@ type WorkerImpl struct {
acl *ACL
findhop *FindHop
snat *cn.FireWallChain
dnat *cn.FireWallChain
}
func NewWorkerApi(c *co.Network) *WorkerImpl {
@@ -107,6 +110,7 @@ func (w *WorkerImpl) Initialize() {
w.fire = cn.NewFireWallTable(cfg.Name)
w.snat = cn.NewFireWallChain("XTT_"+cfg.Name+"_SNAT", cn.TNat, "")
w.dnat = cn.NewFireWallChain("XTT_"+cfg.Name+"_DNAT", cn.TNat, "")
w.setV.Clear()
w.setR.Clear()
@@ -342,7 +346,7 @@ func (w *WorkerImpl) loadVRF() {
}
}
func (w *WorkerImpl) setMss() {
func (w *WorkerImpl) doMss() {
cfg, _ := w.GetCfgs()
mss := cfg.Bridge.Mss
@@ -382,18 +386,20 @@ func (w *WorkerImpl) SetMss(mss int) {
cfg, _ := w.GetCfgs()
if cfg.Bridge.Mss != mss {
cfg.Bridge.Mss = mss
w.setMss()
w.doMss()
}
}
func (w *WorkerImpl) enableSnat() {
func (w *WorkerImpl) doSnat() {
w.out.Info("WorkerImpl: doSnat")
w.fire.Nat.Post.AddRuleX(cn.IPRule{
Jump: w.snat.Chain().Name,
Comment: "Goto SNAT",
})
}
func (w *WorkerImpl) disableSnat() {
func (w *WorkerImpl) undoSnat() {
w.out.Info("WorkerImpl: undoSnat")
w.fire.Nat.Post.DelRuleX(cn.IPRule{
Jump: w.snat.Chain().Name,
Comment: "Goto SNAT",
@@ -404,7 +410,7 @@ func (w *WorkerImpl) EnableSnat() {
cfg, _ := w.GetCfgs()
if cfg.Snat == "disable" {
cfg.Snat = "enable"
w.enableSnat()
w.doSnat()
}
}
@@ -412,10 +418,97 @@ func (w *WorkerImpl) DisableSnat() {
cfg, _ := w.GetCfgs()
if cfg.Snat != "disable" {
cfg.Snat = "disable"
w.disableSnat()
w.undoSnat()
}
}
func (w *WorkerImpl) doDnat() {
cfg, _ := w.GetCfgs()
w.out.Info("WorkerImpl: doDnat")
w.fire.Nat.Pre.AddRuleX(cn.IPRule{
Jump: w.dnat.Chain().Name,
Comment: "Goto DNAT",
})
for _, obj := range cfg.Dnat {
if err := w.dnat.AddRuleX(cn.IPRule{
Proto: obj.Protocol,
Dest: obj.Dest,
DstPort: fmt.Sprintf("%d", obj.Dport),
ToDest: fmt.Sprintf("%s:%d", obj.ToDest, obj.ToDport),
Jump: "DNAT",
Comment: "DNAT " + obj.Id(),
}); err != nil {
w.out.Warn("WorkerImple: doDnat: %s", err)
}
}
}
func (w *WorkerImpl) AddDnat(data schema.DNAT) error {
cfg, _ := w.GetCfgs()
obj := config.Dnat{
Protocol: data.Protocol,
Dest: data.Dest,
Dport: data.Dport,
ToDest: data.ToDest,
ToDport: data.ToDport,
}
obj.Correct()
if ok := cfg.AddDnat(&obj); ok {
if err := w.dnat.AddRuleX(cn.IPRule{
Proto: obj.Protocol,
Dest: obj.Dest,
DstPort: fmt.Sprintf("%d", obj.Dport),
ToDest: fmt.Sprintf("%s:%d", obj.ToDest, obj.ToDport),
Jump: "DNAT",
Comment: "DNAT " + obj.Id(),
}); err != nil {
w.out.Warn("WorkerImple: AddDnat: %s", err)
}
}
return nil
}
func (w *WorkerImpl) DelDnat(data schema.DNAT) error {
cfg, _ := w.GetCfgs()
obj := config.Dnat{
Protocol: data.Protocol,
Dest: data.Dest,
Dport: data.Dport,
ToDest: data.ToDest,
ToDport: data.ToDport,
}
obj.Correct()
if _, ok := cfg.DelDnat(&obj); ok {
if err := w.dnat.DelRuleX(cn.IPRule{
Proto: obj.Protocol,
Dest: obj.Dest,
DstPort: fmt.Sprintf("%d", obj.Dport),
ToDest: fmt.Sprintf("%s:%d", obj.ToDest, obj.ToDport),
Jump: "DNAT",
Comment: "DNAT " + obj.Id(),
}); err != nil {
w.out.Warn("WorkerImple: DelDnat: %s", err)
}
}
return nil
}
func (w *WorkerImpl) ListDnat(call func(data schema.DNAT)) {
cfg, _ := w.GetCfgs()
cfg.ListDnat(func(value config.Dnat) {
call(schema.DNAT{
Protocol: value.Protocol,
Dest: value.Dest,
Dport: value.Dport,
ToDest: value.ToDest,
ToDport: value.ToDport,
})
})
}
func (w *WorkerImpl) doTrust() {
_, vpn := w.GetCfgs()
w.fire.Mangle.Pre.AddRuleX(cn.IPRule{
@@ -425,7 +518,7 @@ func (w *WorkerImpl) doTrust() {
})
}
func (w *WorkerImpl) disableTrust() {
func (w *WorkerImpl) undoTrust() {
_, vpn := w.GetCfgs()
w.fire.Mangle.Pre.DelRuleX(cn.IPRule{
Input: vpn.Device,
@@ -446,7 +539,7 @@ func (w *WorkerImpl) DisableZTrust() {
cfg, _ := w.GetCfgs()
if cfg.ZTrust == "enable" {
cfg.ZTrust = "disable"
w.disableTrust()
w.undoTrust()
}
}
@@ -482,7 +575,7 @@ func (w *WorkerImpl) setVPN2VRF() {
})
}
func (w *WorkerImpl) Start(v api.Switcher) {
func (w *WorkerImpl) Start(v api.SwitchApi) {
cfg, vpn := w.GetCfgs()
w.out.Info("WorkerImpl.Start")
@@ -514,12 +607,15 @@ func (w *WorkerImpl) Start(v api.Switcher) {
w.fire.Start()
w.snat.Install()
w.dnat.Install()
w.doDnat()
if cfg.Snat != "disable" {
w.enableSnat()
w.doSnat()
}
if cfg.Bridge.Mss > 0 {
// forward to remote
w.setMss()
w.doMss()
}
w.findhop.Start()
@@ -636,10 +732,11 @@ func (w *WorkerImpl) Stop() {
cfg, _ := w.GetCfgs()
if cfg.Snat != "disable" {
w.disableSnat()
w.undoSnat()
}
w.snat.Cancel()
w.dnat.Cancel()
w.fire.Stop()
w.findhop.Stop()
w.acl.Stop()
@@ -707,7 +804,7 @@ func (w *WorkerImpl) Subnet() *net.IPNet {
return nil
}
func (w *WorkerImpl) Reload(v api.Switcher) {
func (w *WorkerImpl) Reload(v api.SwitchApi) {
}
func (w *WorkerImpl) toACL(input string) {
@@ -1069,7 +1166,7 @@ func (w *WorkerImpl) ListRoute(call func(obj schema.PrefixRoute)) {
})
}
func (w *WorkerImpl) AddRoute(route *schema.PrefixRoute, switcher api.Switcher) error {
func (w *WorkerImpl) AddRoute(route *schema.PrefixRoute, v api.SwitchApi) error {
rt := w.correctRoute(route)
if !w.cfg.AddRoute(rt) {
w.out.Info("WorkerImpl.AddRoute: %s route exist", route.Prefix)
@@ -1086,7 +1183,7 @@ func (w *WorkerImpl) AddRoute(route *schema.PrefixRoute, switcher api.Switcher)
return nil
}
func (w *WorkerImpl) DelRoute(route *schema.PrefixRoute, switcher api.Switcher) error {
func (w *WorkerImpl) DelRoute(route *schema.PrefixRoute, v api.SwitchApi) error {
correctRt := w.correctRoute(route)
delRt, removed := w.cfg.DelRoute(correctRt)
if !removed {
@@ -1107,7 +1204,7 @@ func (w *WorkerImpl) SaveRoute() {
w.cfg.SaveRoute()
}
func (w *WorkerImpl) Router() api.Router {
func (w *WorkerImpl) Router() api.RouteApi {
return w
}
@@ -1146,18 +1243,19 @@ func (w *WorkerImpl) DelOutput(data schema.Output) {
func (w *WorkerImpl) SaveOutput() {
w.cfg.SaveOutput()
}
func (w *WorkerImpl) ZTruster() api.ZTruster {
func (w *WorkerImpl) ZTruster() api.ZTrustApi {
return w.ztrust
}
func (w *WorkerImpl) Qoser() api.Qoser {
func (w *WorkerImpl) Qoser() api.QosApi {
return w.qos
}
func (w *WorkerImpl) ACLer() api.ACLer {
func (w *WorkerImpl) ACLer() api.ACLApi {
return w.acl
}
func (w *WorkerImpl) FindHoper() api.FindHoper {
func (w *WorkerImpl) FindHoper() api.FindHopApi {
return w.findhop
}

View File

@@ -86,7 +86,7 @@ func (w *OpenLANWorker) UpBridge(cfg *co.Bridge) {
}
}
func (w *OpenLANWorker) Start(v api.Switcher) {
func (w *OpenLANWorker) Start(v api.SwitchApi) {
w.uuid = v.UUID()
w.startTime = time.Now().Unix()
@@ -143,7 +143,7 @@ func (w *OpenLANWorker) DelLink(addr string) {
}
}
func (w *OpenLANWorker) Reload(v api.Switcher) {
func (w *OpenLANWorker) Reload(v api.SwitchApi) {
w.Stop()
w.Initialize()
w.Start(v)

View File

@@ -69,7 +69,7 @@ func (w *RouterWorker) addAddress() error {
return nil
}
func (w *RouterWorker) Start(v api.Switcher) {
func (w *RouterWorker) Start(v api.SwitchApi) {
w.uuid = v.UUID()
w.WorkerImpl.Start(v)
w.addAddress()
@@ -96,7 +96,7 @@ func (w *RouterWorker) Stop() {
w.WorkerImpl.Stop()
}
func (w *RouterWorker) Reload(v api.Switcher) {
func (w *RouterWorker) Reload(v api.SwitchApi) {
w.Stop()
w.Initialize()
w.Start(v)

View File

@@ -100,7 +100,7 @@ type Switch struct {
hooks []Hook
http *Http
server libol.SocketServer
worker map[string]api.Networker
worker map[string]api.NetworkApi
uuid string
newTime int64
out *libol.SubLogger
@@ -111,7 +111,7 @@ func NewSwitch(c *co.Switch) *Switch {
v := &Switch{
cfg: c,
fire: network.NewFireWallGlobal(c.FireWall),
worker: make(map[string]api.Networker, 32),
worker: make(map[string]api.NetworkApi, 32),
server: server,
newTime: time.Now().Unix(),
hooks: make([]Hook, 0, 64),