mirror of
https://github.com/luscis/openlan.git
synced 2025-10-11 19:40:08 +08:00
fea: add commands for zero trust
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "os"
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
func GetEnv(key, value string) string {
|
func GetEnv(key, value string) string {
|
||||||
val := os.Getenv(key)
|
val := os.Getenv(key)
|
||||||
@@ -9,3 +12,19 @@ func GetEnv(key, value string) string {
|
|||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SplitName(name string) (string, string) {
|
||||||
|
values := strings.SplitN(name, "@", 2)
|
||||||
|
if len(values) == 2 {
|
||||||
|
return values[0], values[1]
|
||||||
|
}
|
||||||
|
return name, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func SplitSocket(value string) (string, string) {
|
||||||
|
values := strings.SplitN(value, ":", 2)
|
||||||
|
if len(values) == 2 {
|
||||||
|
return values[0], values[1]
|
||||||
|
}
|
||||||
|
return value, ""
|
||||||
|
}
|
||||||
|
@@ -44,4 +44,6 @@ func Commands(app *api.App) {
|
|||||||
Policy{}.Commands(app)
|
Policy{}.Commands(app)
|
||||||
Version{}.Commands(app)
|
Version{}.Commands(app)
|
||||||
Log{}.Commands(app)
|
Log{}.Commands(app)
|
||||||
|
ZGuest{}.Commands(app)
|
||||||
|
Knock{}.Commands(app)
|
||||||
}
|
}
|
||||||
|
112
cmd/api/v5/knock.go
Executable file
112
cmd/api/v5/knock.go
Executable file
@@ -0,0 +1,112 @@
|
|||||||
|
package v5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/luscis/openlan/cmd/api"
|
||||||
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
|
"github.com/luscis/openlan/pkg/schema"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Knock struct {
|
||||||
|
Cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Knock) Url(prefix, name string) string {
|
||||||
|
name, network := api.SplitName(name)
|
||||||
|
return prefix + "/api/ztrust/" + network + "/guest/" + name + "/knock"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Knock) Add(c *cli.Context) error {
|
||||||
|
username := c.String("name")
|
||||||
|
if !strings.Contains(username, "@") {
|
||||||
|
return libol.NewErr("invalid username")
|
||||||
|
}
|
||||||
|
socket := c.String("socket")
|
||||||
|
knock := &schema.KnockRule{
|
||||||
|
Protocl: c.String("protocol"),
|
||||||
|
}
|
||||||
|
knock.Name, knock.Network = api.SplitName(username)
|
||||||
|
knock.Dest, knock.Port = api.SplitSocket(socket)
|
||||||
|
|
||||||
|
url := u.Url(c.String("url"), username)
|
||||||
|
clt := u.NewHttp(c.String("token"))
|
||||||
|
if err := clt.PostJSON(url, knock, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Knock) Remove(c *cli.Context) error {
|
||||||
|
username := c.String("name")
|
||||||
|
if !strings.Contains(username, "@") {
|
||||||
|
return libol.NewErr("invalid username")
|
||||||
|
}
|
||||||
|
socket := c.String("socket")
|
||||||
|
knock := &schema.KnockRule{
|
||||||
|
Protocl: c.String("protocol"),
|
||||||
|
}
|
||||||
|
knock.Name, knock.Network = api.SplitName(username)
|
||||||
|
knock.Dest, knock.Port = api.SplitSocket(socket)
|
||||||
|
|
||||||
|
url := u.Url(c.String("url"), username)
|
||||||
|
clt := u.NewHttp(c.String("token"))
|
||||||
|
if err := clt.DeleteJSON(url, knock, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Knock) Tmpl() string {
|
||||||
|
return `# total {{ len . }}
|
||||||
|
{{ps -24 "username"}} {{ps -24 "address"}}
|
||||||
|
{{- range . }}
|
||||||
|
{{p2 -24 "%s@%s" .Name .Network}} {{ps -24 .Address}}
|
||||||
|
{{- end }}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Knock) List(c *cli.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u Knock) Commands(app *api.App) {
|
||||||
|
app.Command(&cli.Command{
|
||||||
|
Name: "knock",
|
||||||
|
Aliases: []string{"kn"},
|
||||||
|
Usage: "Knock configuration",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
{
|
||||||
|
Name: "add",
|
||||||
|
Usage: "Add a knock",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{Name: "name"},
|
||||||
|
&cli.StringFlag{Name: "protocol"},
|
||||||
|
&cli.StringFlag{Name: "socket"},
|
||||||
|
},
|
||||||
|
Action: u.Add,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "remove",
|
||||||
|
Usage: "Remove an existing knock",
|
||||||
|
Aliases: []string{"rm"},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{Name: "name"},
|
||||||
|
&cli.StringFlag{Name: "protocol"},
|
||||||
|
&cli.StringFlag{Name: "socket"},
|
||||||
|
},
|
||||||
|
Action: u.Remove,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "list",
|
||||||
|
Usage: "Display all knock",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{Name: "network"},
|
||||||
|
},
|
||||||
|
Action: u.List,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@@ -51,7 +51,7 @@ func (u Point) Commands(app *api.App) {
|
|||||||
app.Command(&cli.Command{
|
app.Command(&cli.Command{
|
||||||
Name: "point",
|
Name: "point",
|
||||||
Aliases: []string{"ap"},
|
Aliases: []string{"ap"},
|
||||||
Usage: "Point connected to this",
|
Usage: "Point accessed to switch",
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
|
@@ -26,22 +26,17 @@ func (u User) Url(prefix, name string) string {
|
|||||||
|
|
||||||
func (u User) Add(c *cli.Context) error {
|
func (u User) Add(c *cli.Context) error {
|
||||||
username := c.String("name")
|
username := c.String("name")
|
||||||
|
if !strings.Contains(username, "@") {
|
||||||
|
return libol.NewErr("invalid username")
|
||||||
|
}
|
||||||
user := &schema.User{
|
user := &schema.User{
|
||||||
Name: username,
|
Name: username,
|
||||||
Password: c.String("password"),
|
Password: c.String("password"),
|
||||||
Role: c.String("role"),
|
Role: c.String("role"),
|
||||||
Lease: c.String("lease"),
|
Lease: c.String("lease"),
|
||||||
}
|
}
|
||||||
if user.Name == "" {
|
user.Name, user.Network = api.SplitName(username)
|
||||||
return libol.NewErr("name is empty")
|
url := u.Url(c.String("url"), username)
|
||||||
}
|
|
||||||
if !strings.Contains(username, "@") {
|
|
||||||
return libol.NewErr("name not contains network")
|
|
||||||
}
|
|
||||||
values := strings.SplitN(username, "@", 2)
|
|
||||||
user.Name = values[0]
|
|
||||||
user.Network = values[1]
|
|
||||||
url := u.Url(c.String("url"), user.Name)
|
|
||||||
clt := u.NewHttp(c.String("token"))
|
clt := u.NewHttp(c.String("token"))
|
||||||
if err := clt.PostJSON(url, user, nil); err != nil {
|
if err := clt.PostJSON(url, user, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
|
110
cmd/api/v5/zguest.go
Executable file
110
cmd/api/v5/zguest.go
Executable file
@@ -0,0 +1,110 @@
|
|||||||
|
package v5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/luscis/openlan/cmd/api"
|
||||||
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
|
"github.com/luscis/openlan/pkg/schema"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZGuest struct {
|
||||||
|
Cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u ZGuest) Url(prefix, name string) string {
|
||||||
|
name, network := api.SplitName(name)
|
||||||
|
if name == "" {
|
||||||
|
return prefix + "/api/ztrust/" + network + "/guest"
|
||||||
|
} else {
|
||||||
|
return prefix + "/api/ztrust/" + network + "/guest/" + name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u ZGuest) Add(c *cli.Context) error {
|
||||||
|
username := c.String("name")
|
||||||
|
if !strings.Contains(username, "@") {
|
||||||
|
return libol.NewErr("invalid username")
|
||||||
|
}
|
||||||
|
guest := &schema.ZGuest{
|
||||||
|
Name: username,
|
||||||
|
Address: c.String("address"),
|
||||||
|
}
|
||||||
|
guest.Name, guest.Network = api.SplitName(username)
|
||||||
|
url := u.Url(c.String("url"), username)
|
||||||
|
clt := u.NewHttp(c.String("token"))
|
||||||
|
if err := clt.PostJSON(url, guest, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u ZGuest) Remove(c *cli.Context) error {
|
||||||
|
username := c.String("name")
|
||||||
|
if !strings.Contains(username, "@") {
|
||||||
|
return libol.NewErr("invalid username")
|
||||||
|
}
|
||||||
|
guest := &schema.ZGuest{
|
||||||
|
Name: username,
|
||||||
|
Address: c.String("address"),
|
||||||
|
}
|
||||||
|
guest.Name, guest.Network = api.SplitName(username)
|
||||||
|
url := u.Url(c.String("url"), username)
|
||||||
|
clt := u.NewHttp(c.String("token"))
|
||||||
|
if err := clt.DeleteJSON(url, guest, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u ZGuest) Tmpl() string {
|
||||||
|
return `# total {{ len . }}
|
||||||
|
{{ps -24 "username"}} {{ps -24 "address"}}
|
||||||
|
{{- range . }}
|
||||||
|
{{p2 -24 "%s@%s" .Name .Network}} {{ps -24 .Address}}
|
||||||
|
{{- end }}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u ZGuest) List(c *cli.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u ZGuest) Commands(app *api.App) {
|
||||||
|
app.Command(&cli.Command{
|
||||||
|
Name: "zguest",
|
||||||
|
Aliases: []string{"zg"},
|
||||||
|
Usage: "zGuest configuration",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
{
|
||||||
|
Name: "add",
|
||||||
|
Usage: "Add a zGuest",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{Name: "name"},
|
||||||
|
&cli.StringFlag{Name: "address"},
|
||||||
|
},
|
||||||
|
Action: u.Add,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "remove",
|
||||||
|
Usage: "Remove an existing zGuest",
|
||||||
|
Aliases: []string{"rm"},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{Name: "name"},
|
||||||
|
&cli.StringFlag{Name: "address"},
|
||||||
|
},
|
||||||
|
Action: u.Remove,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "list",
|
||||||
|
Usage: "Display all zGuests",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{Name: "network"},
|
||||||
|
},
|
||||||
|
Action: u.List,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@@ -1,12 +1,13 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/luscis/openlan/pkg/cache"
|
"github.com/luscis/openlan/pkg/cache"
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
"github.com/luscis/openlan/pkg/models"
|
"github.com/luscis/openlan/pkg/models"
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
"github.com/luscis/openlan/pkg/schema"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Link struct {
|
type Link struct {
|
||||||
@@ -31,7 +32,7 @@ func (h Link) List(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func (h Link) Get(w http.ResponseWriter, r *http.Request) {
|
func (h Link) Get(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
libol.Info("GetPoint %s", vars["id"])
|
libol.Info("Link.Get %s", vars["id"])
|
||||||
|
|
||||||
link := cache.Link.Get(vars["id"])
|
link := cache.Link.Get(vars["id"])
|
||||||
if link != nil {
|
if link != nil {
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/luscis/openlan/pkg/config"
|
co "github.com/luscis/openlan/pkg/config"
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
|
cn "github.com/luscis/openlan/pkg/network"
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
"github.com/luscis/openlan/pkg/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ type Switcher interface {
|
|||||||
UUID() string
|
UUID() string
|
||||||
UpTime() int64
|
UpTime() int64
|
||||||
Alias() string
|
Alias() string
|
||||||
Config() *config.Switch
|
Config() *co.Switch
|
||||||
Server() libol.SocketServer
|
Server() libol.SocketServer
|
||||||
Reload()
|
Reload()
|
||||||
Save()
|
Save()
|
||||||
@@ -28,3 +29,39 @@ func NewWorkerSchema(s Switcher) schema.Worker {
|
|||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ZTruster interface {
|
||||||
|
AddGuest(name, source string) error
|
||||||
|
DelGuest(name, source string) error
|
||||||
|
Knock(name string, protocol, dest, port string, age int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Networker interface {
|
||||||
|
String() string
|
||||||
|
ID() string
|
||||||
|
Initialize()
|
||||||
|
Start(v Switcher)
|
||||||
|
Stop()
|
||||||
|
Bridge() cn.Bridger
|
||||||
|
Config() *co.Network
|
||||||
|
Subnet() string
|
||||||
|
Reload(v Switcher)
|
||||||
|
Provider() string
|
||||||
|
ZTruster() ZTruster
|
||||||
|
}
|
||||||
|
|
||||||
|
var workers = make(map[string]Networker)
|
||||||
|
|
||||||
|
func AddWorker(name string, obj Networker) {
|
||||||
|
workers[name] = obj
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWorker(name string) Networker {
|
||||||
|
return workers[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListWorker(call func(w Networker)) {
|
||||||
|
for _, worker := range workers {
|
||||||
|
call(worker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -22,4 +22,5 @@ func Add(router *mux.Router, switcher Switcher) {
|
|||||||
Version{}.Router(router)
|
Version{}.Router(router)
|
||||||
Log{}.Router(router)
|
Log{}.Router(router)
|
||||||
OpenAPI{}.Router(router)
|
OpenAPI{}.Router(router)
|
||||||
|
ZTrust{}.Router(router)
|
||||||
}
|
}
|
||||||
|
140
pkg/api/ztrust.go
Executable file
140
pkg/api/ztrust.go
Executable file
@@ -0,0 +1,140 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
|
"github.com/luscis/openlan/pkg/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZTrust struct {
|
||||||
|
Switcher Switcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) Router(router *mux.Router) {
|
||||||
|
router.HandleFunc("/api/ztrust", h.List).Methods("GET")
|
||||||
|
router.HandleFunc("/api/ztrust/{id}", h.Get).Methods("GET")
|
||||||
|
router.HandleFunc("/api/ztrust/{id}/guest/{user}", h.GetGuest).Methods("GET")
|
||||||
|
router.HandleFunc("/api/ztrust/{id}/guest/{user}", h.AddGuest).Methods("POST")
|
||||||
|
router.HandleFunc("/api/ztrust/{id}/guest/{user}", h.DelGuest).Methods("DELETE")
|
||||||
|
router.HandleFunc("/api/ztrust/{id}/guest/{user}/knock", h.ListKnock).Methods("GET")
|
||||||
|
router.HandleFunc("/api/ztrust/{id}/guest/{user}/knock", h.AddKnock).Methods("POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) List(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ResponseJson(w, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) Get(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
libol.Info("ZTrust.GET %s", vars["id"])
|
||||||
|
ResponseJson(w, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) GetGuest(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
libol.Info("ZTrust.AddGuest %s", vars["id"])
|
||||||
|
ResponseJson(w, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) AddGuest(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id := vars["id"]
|
||||||
|
|
||||||
|
worker := GetWorker(id)
|
||||||
|
if worker == nil {
|
||||||
|
http.Error(w, "Network not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ztrust := worker.ZTruster()
|
||||||
|
if ztrust == nil {
|
||||||
|
http.Error(w, "ZTrust disabled", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guest := &schema.ZGuest{}
|
||||||
|
if err := GetData(r, guest); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guest.Name = vars["user"]
|
||||||
|
libol.Info("ZTrust.AddGuest %s@%s", guest.Name, id)
|
||||||
|
|
||||||
|
if err := ztrust.AddGuest(guest.Name, guest.Address); err == nil {
|
||||||
|
ResponseJson(w, "success")
|
||||||
|
} else {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) DelGuest(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id := vars["id"]
|
||||||
|
|
||||||
|
worker := GetWorker(id)
|
||||||
|
if worker == nil {
|
||||||
|
http.Error(w, "Network not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ztrust := worker.ZTruster()
|
||||||
|
if ztrust == nil {
|
||||||
|
http.Error(w, "ZTrust disabled", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guest := &schema.ZGuest{}
|
||||||
|
if err := GetData(r, guest); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guest.Name = vars["user"]
|
||||||
|
libol.Info("ZTrust.DelGuest %s@%s", guest.Name, id)
|
||||||
|
if err := ztrust.DelGuest(guest.Name, guest.Address); err == nil {
|
||||||
|
ResponseJson(w, "success")
|
||||||
|
} else {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) ListKnock(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
libol.Info("ZTrust.ListKnock %s", vars["id"])
|
||||||
|
ResponseJson(w, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ZTrust) AddKnock(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
|
id := vars["id"]
|
||||||
|
|
||||||
|
worker := GetWorker(id)
|
||||||
|
if worker == nil {
|
||||||
|
http.Error(w, "Network not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ztrust := worker.ZTruster()
|
||||||
|
if ztrust == nil {
|
||||||
|
http.Error(w, "ZTrust disabled", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule := &schema.KnockRule{}
|
||||||
|
if err := GetData(r, rule); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name := vars["user"]
|
||||||
|
libol.Info("ZTrust.AddKnock %s@%s", rule.Name, id)
|
||||||
|
|
||||||
|
if err := ztrust.Knock(name, rule.Protocl, rule.Dest, rule.Port, 0); err == nil {
|
||||||
|
ResponseJson(w, "success")
|
||||||
|
} else {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@@ -23,7 +23,7 @@ type Network struct {
|
|||||||
Specifies interface{} `json:"specifies,omitempty"`
|
Specifies interface{} `json:"specifies,omitempty"`
|
||||||
Dhcp string `json:"dhcp,omitempty"`
|
Dhcp string `json:"dhcp,omitempty"`
|
||||||
Outputs []Output `json:"outputs"`
|
Outputs []Output `json:"outputs"`
|
||||||
ZeroTrust string `json:"zerotrust"`
|
ZTrust string `json:"ztrust"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Network) NewSpecifies() interface{} {
|
func (n *Network) NewSpecifies() interface{} {
|
||||||
|
17
pkg/schema/ztrust.go
Executable file
17
pkg/schema/ztrust.go
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
type ZGuest struct {
|
||||||
|
Network string `json:"network"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Device string `json:"device"`
|
||||||
|
Address string `json:"Address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KnockRule struct {
|
||||||
|
Network string `json:"network"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Dest string `json:"destination"`
|
||||||
|
Protocl string `json:"protocol"`
|
||||||
|
Port string `json:"port"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
}
|
@@ -147,7 +147,7 @@ func (c *ConfD) DiffLink(old *database.VirtualLink, new *database.VirtualLink) b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConfD) AddLink(obj *database.VirtualLink) {
|
func (c *ConfD) AddLink(obj *database.VirtualLink) {
|
||||||
worker := GetWorker(obj.Network)
|
worker := api.GetWorker(obj.Network)
|
||||||
if worker == nil {
|
if worker == nil {
|
||||||
c.out.Warn("ConfD.AddLink network %s not found.", obj.Network)
|
c.out.Warn("ConfD.AddLink network %s not found.", obj.Network)
|
||||||
return
|
return
|
||||||
@@ -179,7 +179,7 @@ func (c *ConfD) AddLink(obj *database.VirtualLink) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConfD) DelLink(obj *database.VirtualLink) {
|
func (c *ConfD) DelLink(obj *database.VirtualLink) {
|
||||||
worker := GetWorker(obj.Network)
|
worker := api.GetWorker(obj.Network)
|
||||||
if worker == nil {
|
if worker == nil {
|
||||||
c.out.Warn("ConfD.DelLink network %s not found.", obj.Network)
|
c.out.Warn("ConfD.DelLink network %s not found.", obj.Network)
|
||||||
return
|
return
|
||||||
@@ -215,7 +215,7 @@ func (c *ConfD) UpdateName(obj *database.NameCache) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.out.Info("ConfD.UpdateName %s %s", obj.Name, obj.Address)
|
c.out.Info("ConfD.UpdateName %s %s", obj.Name, obj.Address)
|
||||||
ListWorker(func(w Networker) {
|
api.ListWorker(func(w api.Networker) {
|
||||||
cfg := w.Config()
|
cfg := w.Config()
|
||||||
spec := cfg.Specifies
|
spec := cfg.Specifies
|
||||||
if spec == nil {
|
if spec == nil {
|
||||||
@@ -235,7 +235,7 @@ func (c *ConfD) AddRoute(obj *database.PrefixRoute) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
||||||
worker := GetWorker(obj.Network)
|
worker := api.GetWorker(obj.Network)
|
||||||
if worker == nil {
|
if worker == nil {
|
||||||
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
||||||
return
|
return
|
||||||
@@ -273,7 +273,7 @@ func (c *ConfD) DelRoute(obj *database.PrefixRoute) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
||||||
worker := GetWorker(obj.Network)
|
worker := api.GetWorker(obj.Network)
|
||||||
if worker == nil {
|
if worker == nil {
|
||||||
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
||||||
return
|
return
|
||||||
@@ -297,7 +297,7 @@ func (c *ConfD) DelRoute(obj *database.PrefixRoute) {
|
|||||||
type LinkImpl struct {
|
type LinkImpl struct {
|
||||||
api api.Switcher
|
api api.Switcher
|
||||||
out *libol.SubLogger
|
out *libol.SubLogger
|
||||||
worker Networker
|
worker api.Networker
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LinkImpl) Add(obj *database.VirtualLink) {
|
func (l *LinkImpl) Add(obj *database.VirtualLink) {
|
||||||
|
@@ -221,7 +221,7 @@ func (w *FabricWorker) Initialize() {
|
|||||||
}
|
}
|
||||||
_ = w.ovs.setMode("secure")
|
_ = w.ovs.setMode("secure")
|
||||||
w.upTables()
|
w.upTables()
|
||||||
ListWorker(func(n Networker) {
|
api.ListWorker(func(n api.Networker) {
|
||||||
if w.IsSlave(n) {
|
if w.IsSlave(n) {
|
||||||
n.Initialize()
|
n.Initialize()
|
||||||
}
|
}
|
||||||
@@ -441,7 +441,7 @@ func (w *FabricWorker) Start(v api.Switcher) {
|
|||||||
w.AddTunnel(*tunnel)
|
w.AddTunnel(*tunnel)
|
||||||
}
|
}
|
||||||
w.WorkerImpl.Start(v)
|
w.WorkerImpl.Start(v)
|
||||||
ListWorker(func(n Networker) {
|
api.ListWorker(func(n api.Networker) {
|
||||||
if w.IsSlave(n) {
|
if w.IsSlave(n) {
|
||||||
n.Start(v)
|
n.Start(v)
|
||||||
}
|
}
|
||||||
@@ -471,7 +471,7 @@ func (w *FabricWorker) DelTunnel(name string) {
|
|||||||
_ = w.ovs.delPort(name)
|
_ = w.ovs.delPort(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *FabricWorker) IsSlave(n Networker) bool {
|
func (w *FabricWorker) IsSlave(n api.Networker) bool {
|
||||||
cfg := n.Config()
|
cfg := n.Config()
|
||||||
if cfg == nil || cfg.Specifies == nil {
|
if cfg == nil || cfg.Specifies == nil {
|
||||||
return false
|
return false
|
||||||
@@ -485,7 +485,7 @@ func (w *FabricWorker) IsSlave(n Networker) bool {
|
|||||||
|
|
||||||
func (w *FabricWorker) Stop() {
|
func (w *FabricWorker) Stop() {
|
||||||
w.out.Info("FabricWorker.Stop")
|
w.out.Info("FabricWorker.Stop")
|
||||||
ListWorker(func(n Networker) {
|
api.ListWorker(func(n api.Networker) {
|
||||||
if w.IsSlave(n) {
|
if w.IsSlave(n) {
|
||||||
n.Stop()
|
n.Stop()
|
||||||
}
|
}
|
||||||
|
@@ -13,23 +13,8 @@ import (
|
|||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Networker interface {
|
func NewNetworker(c *co.Network) api.Networker {
|
||||||
String() string
|
var obj api.Networker
|
||||||
ID() string
|
|
||||||
Initialize()
|
|
||||||
Start(v api.Switcher)
|
|
||||||
Stop()
|
|
||||||
Bridge() cn.Bridger
|
|
||||||
Config() *co.Network
|
|
||||||
Subnet() string
|
|
||||||
Reload(v api.Switcher)
|
|
||||||
Provider() string
|
|
||||||
}
|
|
||||||
|
|
||||||
var workers = make(map[string]Networker)
|
|
||||||
|
|
||||||
func NewNetworker(c *co.Network) Networker {
|
|
||||||
var obj Networker
|
|
||||||
switch c.Provider {
|
switch c.Provider {
|
||||||
case "esp":
|
case "esp":
|
||||||
obj = NewESPWorker(c)
|
obj = NewESPWorker(c)
|
||||||
@@ -42,20 +27,10 @@ func NewNetworker(c *co.Network) Networker {
|
|||||||
default:
|
default:
|
||||||
obj = NewOpenLANWorker(c)
|
obj = NewOpenLANWorker(c)
|
||||||
}
|
}
|
||||||
workers[c.Name] = obj
|
api.AddWorker(c.Name, obj)
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWorker(name string) Networker {
|
|
||||||
return workers[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
func ListWorker(call func(w Networker)) {
|
|
||||||
for _, worker := range workers {
|
|
||||||
call(worker)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type LinuxPort struct {
|
type LinuxPort struct {
|
||||||
name string // gre:xx, vxlan:xx
|
name string // gre:xx, vxlan:xx
|
||||||
vlan int
|
vlan int
|
||||||
@@ -72,7 +47,7 @@ type WorkerImpl struct {
|
|||||||
setR *cn.IPSet
|
setR *cn.IPSet
|
||||||
setV *cn.IPSet
|
setV *cn.IPSet
|
||||||
vpn *OpenVPN
|
vpn *OpenVPN
|
||||||
trust *ZeroTrust
|
ztrust *ZTrust
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorkerApi(c *co.Network) *WorkerImpl {
|
func NewWorkerApi(c *co.Network) *WorkerImpl {
|
||||||
@@ -104,9 +79,9 @@ func (w *WorkerImpl) Initialize() {
|
|||||||
w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err)
|
w.out.Error("WorkImpl.Initialize: create ipset: %s %s", out, err)
|
||||||
}
|
}
|
||||||
w.newVPN()
|
w.newVPN()
|
||||||
if w.cfg.ZeroTrust == "enable" {
|
if w.cfg.ZTrust == "enable" {
|
||||||
w.trust = NewZeroTrust(w.cfg.Name, 30)
|
w.ztrust = NewZTrust(w.cfg.Name, 30)
|
||||||
w.trust.Initialize()
|
w.ztrust.Initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,11 +223,11 @@ func (w *WorkerImpl) Start(v api.Switcher) {
|
|||||||
w.vpn.Start()
|
w.vpn.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(w.vpn == nil || w.trust == nil) {
|
if !(w.vpn == nil || w.ztrust == nil) {
|
||||||
w.trust.Start()
|
w.ztrust.Start()
|
||||||
fire.Mangle.Pre.AddRule(cn.IpRule{
|
fire.Mangle.Pre.AddRule(cn.IpRule{
|
||||||
Input: vpn.Device,
|
Input: vpn.Device,
|
||||||
Jump: w.trust.Chain(),
|
Jump: w.ztrust.Chain(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fire.Start()
|
fire.Start()
|
||||||
@@ -307,8 +282,8 @@ func (w *WorkerImpl) DelOutput(bridge string, port *LinuxPort) {
|
|||||||
func (w *WorkerImpl) Stop() {
|
func (w *WorkerImpl) Stop() {
|
||||||
w.out.Info("WorkerImpl.Stop")
|
w.out.Info("WorkerImpl.Stop")
|
||||||
w.fire.Stop()
|
w.fire.Stop()
|
||||||
if !(w.vpn == nil || w.trust == nil) {
|
if !(w.vpn == nil || w.ztrust == nil) {
|
||||||
w.trust.Stop()
|
w.ztrust.Stop()
|
||||||
}
|
}
|
||||||
if !(w.vpn == nil) {
|
if !(w.vpn == nil) {
|
||||||
w.vpn.Stop()
|
w.vpn.Stop()
|
||||||
@@ -489,3 +464,7 @@ func (w *WorkerImpl) newVPN() {
|
|||||||
obj.Initialize()
|
obj.Initialize()
|
||||||
w.vpn = obj
|
w.vpn = obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *WorkerImpl) ZTruster() api.ZTruster {
|
||||||
|
return w.ztrust
|
||||||
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/luscis/openlan/pkg/api"
|
||||||
"github.com/luscis/openlan/pkg/app"
|
"github.com/luscis/openlan/pkg/app"
|
||||||
"github.com/luscis/openlan/pkg/cache"
|
"github.com/luscis/openlan/pkg/cache"
|
||||||
co "github.com/luscis/openlan/pkg/config"
|
co "github.com/luscis/openlan/pkg/config"
|
||||||
@@ -96,7 +97,7 @@ type Switch struct {
|
|||||||
hooks []Hook
|
hooks []Hook
|
||||||
http *Http
|
http *Http
|
||||||
server libol.SocketServer
|
server libol.SocketServer
|
||||||
worker map[string]Networker
|
worker map[string]api.Networker
|
||||||
uuid string
|
uuid string
|
||||||
newTime int64
|
newTime int64
|
||||||
out *libol.SubLogger
|
out *libol.SubLogger
|
||||||
@@ -110,7 +111,7 @@ func NewSwitch(c *co.Switch) *Switch {
|
|||||||
v := &Switch{
|
v := &Switch{
|
||||||
cfg: c,
|
cfg: c,
|
||||||
fire: network.NewFireWallGlobal(c.FireWall),
|
fire: network.NewFireWallGlobal(c.FireWall),
|
||||||
worker: make(map[string]Networker, 32),
|
worker: make(map[string]api.Networker, 32),
|
||||||
server: server,
|
server: server,
|
||||||
newTime: time.Now().Unix(),
|
newTime: time.Now().Unix(),
|
||||||
hooks: make([]Hook, 0, 64),
|
hooks: make([]Hook, 0, 64),
|
||||||
|
@@ -1,162 +0,0 @@
|
|||||||
package cswitch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
"github.com/luscis/openlan/pkg/network"
|
|
||||||
cn "github.com/luscis/openlan/pkg/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KnockRule struct {
|
|
||||||
createAt int64
|
|
||||||
protocol string
|
|
||||||
dest string
|
|
||||||
destPort string
|
|
||||||
rule *cn.IpRule
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *KnockRule) Id() string {
|
|
||||||
return fmt.Sprintf("%s:%s:%s", r.protocol, r.dest, r.destPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ZeroGuest struct {
|
|
||||||
network string
|
|
||||||
username string
|
|
||||||
device string
|
|
||||||
sources map[string]string
|
|
||||||
rules map[string]*KnockRule
|
|
||||||
chain *cn.FireWallChain
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewZeroGuest(network, name string) *ZeroGuest {
|
|
||||||
return &ZeroGuest{
|
|
||||||
network: network,
|
|
||||||
username: name,
|
|
||||||
sources: make(map[string]string, 2),
|
|
||||||
rules: make(map[string]*KnockRule, 1024),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroGuest) Chain() string {
|
|
||||||
return "ZTT_" + z.network + "_" + z.username
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroGuest) Initialize() {
|
|
||||||
z.chain = cn.NewFireWallChain(z.Chain(), network.TMangle, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroGuest) AddSource(source string) {
|
|
||||||
z.sources[source] = source
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroGuest) DelSource(source string) {
|
|
||||||
if _, ok := z.sources[source]; ok {
|
|
||||||
delete(z.sources, source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroGuest) AddRule(rule *KnockRule) {
|
|
||||||
z.rules[rule.Id()] = rule
|
|
||||||
z.chain.AddRuleX(cn.IpRule{
|
|
||||||
Dest: rule.dest,
|
|
||||||
DstPort: rule.destPort,
|
|
||||||
Jump: "ACCEPT",
|
|
||||||
Comment: time.Now().Local().String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroGuest) DelRule(rule *KnockRule) {
|
|
||||||
if _, ok := z.rules[rule.Id()]; ok {
|
|
||||||
delete(z.rules, rule.Id())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ZeroTrust struct {
|
|
||||||
network string
|
|
||||||
expire int
|
|
||||||
guests map[string]*ZeroGuest
|
|
||||||
chain *cn.FireWallChain
|
|
||||||
out *libol.SubLogger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewZeroTrust(network string, expire int) *ZeroTrust {
|
|
||||||
return &ZeroTrust{
|
|
||||||
network: network,
|
|
||||||
expire: expire,
|
|
||||||
out: libol.NewSubLogger(network),
|
|
||||||
guests: make(map[string]*ZeroGuest, 32),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) Chain() string {
|
|
||||||
return "ZTT_" + z.network
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) Initialize() {
|
|
||||||
z.chain = cn.NewFireWallChain(z.Chain(), network.TMangle, "")
|
|
||||||
z.chain.AddRule(cn.IpRule{
|
|
||||||
Comment: "Zero Trust Default",
|
|
||||||
Jump: "DROP",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) Knock(name string, dest, protocol, destPort string) {
|
|
||||||
guest, ok := z.guests[name]
|
|
||||||
if !ok {
|
|
||||||
z.out.Warn("ZeroTrust.Knock: not found %s", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guest.AddRule(&KnockRule{
|
|
||||||
protocol: protocol,
|
|
||||||
dest: dest,
|
|
||||||
destPort: destPort,
|
|
||||||
createAt: time.Now().Unix(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) Update() {
|
|
||||||
//TODO expire knock rules.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) AddGuest(name, device, source string) {
|
|
||||||
guest, ok := z.guests[name]
|
|
||||||
if !ok {
|
|
||||||
guest = NewZeroGuest(z.network, name)
|
|
||||||
guest.Initialize()
|
|
||||||
z.guests[name] = guest
|
|
||||||
}
|
|
||||||
guest.AddSource(source)
|
|
||||||
z.chain.AddRuleX(cn.IpRule{
|
|
||||||
Input: device,
|
|
||||||
Source: source,
|
|
||||||
Comment: guest.username + "." + guest.network,
|
|
||||||
Jump: guest.Chain(),
|
|
||||||
Order: "-I",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) DelGuest(name, device, source string) {
|
|
||||||
guest, ok := z.guests[name]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.chain.DelRuleX(cn.IpRule{
|
|
||||||
Input: device,
|
|
||||||
Source: source,
|
|
||||||
Comment: guest.username + "." + guest.network,
|
|
||||||
Jump: guest.Chain(),
|
|
||||||
})
|
|
||||||
guest.DelSource(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) Start() {
|
|
||||||
z.out.Info("ZeroTrust.Start")
|
|
||||||
z.chain.Install()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZeroTrust) Stop() {
|
|
||||||
z.out.Info("ZeroTrust.Stop")
|
|
||||||
z.chain.Cancel()
|
|
||||||
}
|
|
217
pkg/switch/ztrust.go
Normal file
217
pkg/switch/ztrust.go
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
package cswitch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
|
"github.com/luscis/openlan/pkg/network"
|
||||||
|
cn "github.com/luscis/openlan/pkg/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KnockRule struct {
|
||||||
|
createAt int64
|
||||||
|
age int
|
||||||
|
protocol string
|
||||||
|
destination string
|
||||||
|
port string
|
||||||
|
rule *cn.IpRule
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *KnockRule) Id() string {
|
||||||
|
return fmt.Sprintf("%s:%s:%s", r.protocol, r.destination, r.port)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ZGuest struct {
|
||||||
|
network string
|
||||||
|
username string
|
||||||
|
sources map[string]string
|
||||||
|
rules map[string]*KnockRule
|
||||||
|
chain *cn.FireWallChain
|
||||||
|
out *libol.SubLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewZGuest(network, name string) *ZGuest {
|
||||||
|
return &ZGuest{
|
||||||
|
network: network,
|
||||||
|
username: name,
|
||||||
|
sources: make(map[string]string, 2),
|
||||||
|
rules: make(map[string]*KnockRule, 1024),
|
||||||
|
out: libol.NewSubLogger(name + "@" + network),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) Chain() string {
|
||||||
|
return "ZTT_" + g.network + "-" + g.username
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) Initialize() {
|
||||||
|
g.chain = cn.NewFireWallChain(g.Chain(), network.TMangle, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) Start() {
|
||||||
|
g.chain.Install()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) AddSource(source string) {
|
||||||
|
g.sources[source] = source
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) DelSource(source string) {
|
||||||
|
if _, ok := g.sources[source]; ok {
|
||||||
|
delete(g.sources, source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) AddRuleX(rule cn.IpRule) {
|
||||||
|
if err := g.chain.AddRuleX(rule); err != nil {
|
||||||
|
g.out.Warn("ZTrust.AddRuleX: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) DelRuleX(rule cn.IpRule) {
|
||||||
|
if err := g.chain.DelRuleX(rule); err != nil {
|
||||||
|
g.out.Warn("ZTrust.DelRuleX: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) AddRule(rule *KnockRule) {
|
||||||
|
g.rules[rule.Id()] = rule
|
||||||
|
g.AddRuleX(cn.IpRule{
|
||||||
|
Dest: rule.destination,
|
||||||
|
DstPort: rule.port,
|
||||||
|
Proto: rule.protocol,
|
||||||
|
Jump: "ACCEPT",
|
||||||
|
Comment: "Knock at " + time.Now().UTC().String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) DelRule(rule *KnockRule) {
|
||||||
|
if _, ok := g.rules[rule.Id()]; ok {
|
||||||
|
delete(g.rules, rule.Id())
|
||||||
|
}
|
||||||
|
g.DelRuleX(cn.IpRule{
|
||||||
|
Proto: rule.protocol,
|
||||||
|
Dest: rule.destination,
|
||||||
|
DstPort: rule.port,
|
||||||
|
Jump: "ACCEPT",
|
||||||
|
Comment: "Knock at " + time.Now().Local().String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ZGuest) Stop() {
|
||||||
|
g.chain.Cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
type ZTrust struct {
|
||||||
|
network string
|
||||||
|
expire int
|
||||||
|
guests map[string]*ZGuest
|
||||||
|
chain *cn.FireWallChain
|
||||||
|
out *libol.SubLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewZTrust(network string, expire int) *ZTrust {
|
||||||
|
return &ZTrust{
|
||||||
|
network: network,
|
||||||
|
expire: expire,
|
||||||
|
out: libol.NewSubLogger(network),
|
||||||
|
guests: make(map[string]*ZGuest, 32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) Chain() string {
|
||||||
|
return "ZTT_" + z.network
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) Initialize() {
|
||||||
|
z.chain = cn.NewFireWallChain(z.Chain(), network.TMangle, "")
|
||||||
|
z.chain.AddRule(cn.IpRule{
|
||||||
|
Comment: "ZTrust Default",
|
||||||
|
Jump: "DROP",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) Knock(name string, protocol, dest, port string, age int) error {
|
||||||
|
guest, ok := z.guests[name]
|
||||||
|
if !ok {
|
||||||
|
return libol.NewErr("Knock: not found %s", name)
|
||||||
|
}
|
||||||
|
guest.AddRule(&KnockRule{
|
||||||
|
protocol: protocol,
|
||||||
|
destination: dest,
|
||||||
|
port: port,
|
||||||
|
createAt: time.Now().Unix(),
|
||||||
|
age: age,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) Update() {
|
||||||
|
//TODO expire knock rules.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) AddRuleX(rule cn.IpRule) {
|
||||||
|
if err := z.chain.AddRuleX(rule); err != nil {
|
||||||
|
z.out.Warn("ZTrust.AddRuleX: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) DelRuleX(rule cn.IpRule) {
|
||||||
|
if err := z.chain.DelRuleX(rule); err != nil {
|
||||||
|
z.out.Warn("ZTrust.DelRuleX: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) AddGuest(name, source string) error {
|
||||||
|
z.out.Info("ZTrust.AddGuest: %s %s", name, source)
|
||||||
|
if source == "" {
|
||||||
|
return libol.NewErr("AddGuest: invalid source")
|
||||||
|
}
|
||||||
|
guest, ok := z.guests[name]
|
||||||
|
if !ok {
|
||||||
|
guest = NewZGuest(z.network, name)
|
||||||
|
guest.Initialize()
|
||||||
|
guest.Start()
|
||||||
|
z.guests[name] = guest
|
||||||
|
}
|
||||||
|
guest.AddSource(source)
|
||||||
|
z.AddRuleX(cn.IpRule{
|
||||||
|
Source: source,
|
||||||
|
Comment: "User " + guest.username + "@" + guest.network,
|
||||||
|
Jump: guest.Chain(),
|
||||||
|
Order: "-I",
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) DelGuest(name, source string) error {
|
||||||
|
if source == "" {
|
||||||
|
return libol.NewErr("DelGuest: invalid source")
|
||||||
|
}
|
||||||
|
guest, ok := z.guests[name]
|
||||||
|
if !ok {
|
||||||
|
return libol.NewErr("DelGuest: not found %s", name)
|
||||||
|
}
|
||||||
|
z.out.Info("ZTrust.DelGuest: %s %s", name, source)
|
||||||
|
z.DelRuleX(cn.IpRule{
|
||||||
|
Source: source,
|
||||||
|
Comment: guest.username + "." + guest.network,
|
||||||
|
Jump: guest.Chain(),
|
||||||
|
})
|
||||||
|
guest.DelSource(source)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) Start() {
|
||||||
|
z.out.Info("ZTrust.Start")
|
||||||
|
z.chain.Install()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZTrust) Stop() {
|
||||||
|
z.out.Info("ZTrust.Stop")
|
||||||
|
z.chain.Cancel()
|
||||||
|
for _, guest := range z.guests {
|
||||||
|
guest.Stop()
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user