mirror of
https://github.com/luscis/openlan.git
synced 2025-10-06 09:06:54 +08:00
fea: discard l2tp, esp, and fabric support.
This commit is contained in:
5
Makefile
5
Makefile
@@ -101,7 +101,6 @@ docker-compose: ## create a compose files
|
|||||||
echo "$ docker-compose up -d"
|
echo "$ docker-compose up -d"
|
||||||
|
|
||||||
linux: env ## build linux binary
|
linux: env ## build linux binary
|
||||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openudp ./cmd/openudp
|
|
||||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan ./cmd/main.go
|
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan ./cmd/main.go
|
||||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-proxy ./cmd/proxy
|
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-proxy ./cmd/proxy
|
||||||
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-point ./cmd/point_linux
|
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-point ./cmd/point_linux
|
||||||
@@ -128,8 +127,8 @@ install: env linux ## install packages
|
|||||||
@cp -rf $(SD)/dist/cert/openlan/ca/ca.crt $(LIN_DIR)/var/openlan/cert
|
@cp -rf $(SD)/dist/cert/openlan/ca/ca.crt $(LIN_DIR)/var/openlan/cert
|
||||||
@cp -rf $(SD)/pkg/public $(LIN_DIR)/var/openlan
|
@cp -rf $(SD)/pkg/public $(LIN_DIR)/var/openlan
|
||||||
@mkdir -p $(LIN_DIR)/usr/bin
|
@mkdir -p $(LIN_DIR)/usr/bin
|
||||||
@cp -rf $(BD)/{openudp,openlan} $(LIN_DIR)/usr/bin
|
@cp -rf $(BD)/{openlan,openlan-switch} $(LIN_DIR)/usr/bin
|
||||||
@cp -rf $(BD)/{openlan-point,openlan-proxy,openlan-switch} $(LIN_DIR)/usr/bin
|
@cp -rf $(BD)/{openlan-point,openlan-proxy} $(LIN_DIR)/usr/bin
|
||||||
@echo "Installed to $(LIN_DIR)"
|
@echo "Installed to $(LIN_DIR)"
|
||||||
|
|
||||||
## cross build for windows
|
## cross build for windows
|
||||||
|
55
README.cn.md
55
README.cn.md
@@ -67,65 +67,10 @@ OpenLAN提供一种局域网数据报文在广域网的传输实现,并能够
|
|||||||
OpenLAN OpenLAN OpenLAN
|
OpenLAN OpenLAN OpenLAN
|
||||||
192.168.1.11/24 192.168.1.12/24 192.168.1.13/24
|
192.168.1.11/24 192.168.1.12/24 192.168.1.13/24
|
||||||
|
|
||||||
### 数据中心全互联网络
|
|
||||||
|
|
||||||
* Underlay for VxLAN over Internet by IPSec.
|
|
||||||
|
|
||||||
47.example.com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
+-------+
|
|
||||||
| vps-47| -- 100.65.0.117
|
|
||||||
+-------+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
SPI-117118 / \ SPI-117119
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
+-------+ +-------+
|
|
||||||
| vps-92| -------------- | vps-12|
|
|
||||||
+-------+ +-------+
|
|
||||||
/ | | \
|
|
||||||
/ | SPI-118119 | \
|
|
||||||
100.65.0.118 | | 100.65.0.119
|
|
||||||
| |
|
|
||||||
92.example.com 12.example.com
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* DCI Subnet: 192.168.x.x over IPSec Network: 100.65.0.x.
|
|
||||||
|
|
||||||
100.65.0.117
|
|
||||||
|
|
|
||||||
eth1.200 --- | --- eth1.100
|
|
||||||
\ | /
|
|
||||||
+--------+
|
|
||||||
| vps-47 |
|
|
||||||
+--------+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
enp2s4.100 --- / \ --- eth4.30
|
|
||||||
\ / \ /
|
|
||||||
+--------+ +--------+
|
|
||||||
| vps-92 | --------------- | vps-12 |
|
|
||||||
+--------+ +--------+
|
|
||||||
/ | | \
|
|
||||||
enp2s4.101 --- | | --- eth4.200
|
|
||||||
| |
|
|
||||||
100.65.0.118 100.65.0.119
|
|
||||||
|
|
||||||
VNI-1023 192.168.30.0/24 [vps-47_eth1.100, vps-92_enp2s4.100, vps-12_eth4.30]
|
|
||||||
VNI-1024 192.168.40.0/24 [vps-47_eth1.200, vps-92_enp2s4.101, vps-12_eth4.200]
|
|
||||||
|
|
||||||
|
|
||||||
## 帮助文档
|
## 帮助文档
|
||||||
- [软件安装](docs/install.md)
|
- [软件安装](docs/install.md)
|
||||||
- [分支接入](docs/central.md)
|
- [分支接入](docs/central.md)
|
||||||
- [多区域互联](docs/multiarea.md)
|
- [多区域互联](docs/multiarea.md)
|
||||||
- [全互连网络](docs/fabric.md)
|
|
||||||
- [IPSec网络](docs/ipsec.md)
|
|
||||||
- [零信任网络](docs/ztrust.md)
|
- [零信任网络](docs/ztrust.md)
|
||||||
- [Docker Compose](docs/docker.md)
|
- [Docker Compose](docs/docker.md)
|
||||||
|
55
README.en.md
55
README.en.md
@@ -65,64 +65,9 @@ If you have more flexible VPN business needs and need to use VPN to access the e
|
|||||||
192.168.1.11/24 192.168.1.12/24 192.168.1.13/24
|
192.168.1.11/24 192.168.1.12/24 192.168.1.13/24
|
||||||
|
|
||||||
|
|
||||||
### Data Center Full Internet
|
|
||||||
|
|
||||||
* Underlay for VxLAN over Internet by IPSec.
|
|
||||||
|
|
||||||
47.example.com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
+-------+
|
|
||||||
| vps-47| -- 100.65.0.117
|
|
||||||
+-------+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
SPI-117118 / \ SPI-117119
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
+-------+ +-------+
|
|
||||||
| vps-92| -------------- | vps-12|
|
|
||||||
+-------+ +-------+
|
|
||||||
/ | | \
|
|
||||||
/ | SPI-118119 | \
|
|
||||||
100.65.0.118 | | 100.65.0.119
|
|
||||||
| |
|
|
||||||
92.example.com 12.example.com
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* DCI Subnet: 192.168.x.x over IPSec Network: 100.65.0.x.
|
|
||||||
|
|
||||||
100.65.0.117
|
|
||||||
|
|
|
||||||
eth1.200 --- | --- eth1.100
|
|
||||||
\ | /
|
|
||||||
+--------+
|
|
||||||
| vps-47 |
|
|
||||||
+--------+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
enp2s4.100 --- / \ --- eth4.30
|
|
||||||
\ / \ /
|
|
||||||
+--------+ +--------+
|
|
||||||
| vps-92 | --------------- | vps-12 |
|
|
||||||
+--------+ +--------+
|
|
||||||
/ | | \
|
|
||||||
enp2s4.101 --- | | --- eth4.200
|
|
||||||
| |
|
|
||||||
100.65.0.118 100.65.0.119
|
|
||||||
|
|
||||||
VNI-1023 192.168.30.0/24 [vps-47_eth1.100, vps-92_enp2s4.100, vps-12_eth4.30]
|
|
||||||
VNI-1024 192.168.40.0/24 [vps-47_eth1.200, vps-92_enp2s4.101, vps-12_eth4.200]
|
|
||||||
|
|
||||||
## Help documents
|
## Help documents
|
||||||
- [Software Installation](docs/install.md)
|
- [Software Installation](docs/install.md)
|
||||||
- [Branch Access](docs/central.md)
|
- [Branch Access](docs/central.md)
|
||||||
- [Multi-region Interconnection](docs/multiarea.md)
|
- [Multi-region Interconnection](docs/multiarea.md)
|
||||||
- [Fullly Interconnected Network](docs/fabric.md)
|
|
||||||
- [IPSec Network](docs/ipsec.md)
|
|
||||||
- [Zero Trust Network](docs/ztrust.md)
|
- [Zero Trust Network](docs/ztrust.md)
|
||||||
- [Docker Compose](docs/docker.md)
|
- [Docker Compose](docs/docker.md)
|
||||||
|
@@ -39,10 +39,7 @@ func Commands(app *api.App) {
|
|||||||
Server{}.Commands(app)
|
Server{}.Commands(app)
|
||||||
Network{}.Commands(app)
|
Network{}.Commands(app)
|
||||||
PProf{}.Commands(app)
|
PProf{}.Commands(app)
|
||||||
Esp{}.Commands(app)
|
|
||||||
VxLAN{}.Commands(app)
|
VxLAN{}.Commands(app)
|
||||||
State{}.Commands(app)
|
|
||||||
Policy{}.Commands(app)
|
|
||||||
Version{}.Commands(app)
|
Version{}.Commands(app)
|
||||||
Log{}.Commands(app)
|
Log{}.Commands(app)
|
||||||
Guest{}.Commands(app)
|
Guest{}.Commands(app)
|
||||||
|
@@ -1,54 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/luscis/openlan/cmd/api"
|
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Esp struct {
|
|
||||||
Cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Esp) Url(prefix, name string) string {
|
|
||||||
if name == "" {
|
|
||||||
return prefix + "/api/esp"
|
|
||||||
} else {
|
|
||||||
return prefix + "/api/esp/" + name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Esp) Tmpl() string {
|
|
||||||
return `# total {{ len . }}
|
|
||||||
{{ps -16 "name"}} {{ps -16 "address"}}
|
|
||||||
{{- range . }}
|
|
||||||
{{ps -16 .Name}} {{ps -16 .Address}}
|
|
||||||
{{- end }}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Esp) List(c *cli.Context) error {
|
|
||||||
url := u.Url(c.String("url"), "")
|
|
||||||
clt := u.NewHttp(c.String("token"))
|
|
||||||
var items []schema.Esp
|
|
||||||
if err := clt.GetJSON(url, &items); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return u.Out(items, c.String("format"), u.Tmpl())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Esp) Commands(app *api.App) {
|
|
||||||
app.Command(&cli.Command{
|
|
||||||
Name: "esp",
|
|
||||||
Aliases: []string{"esp"},
|
|
||||||
Usage: "IPSec ESP configuration",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "list",
|
|
||||||
Usage: "Display all esp",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Action: u.List,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/luscis/openlan/cmd/api"
|
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Policy struct {
|
|
||||||
Cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Policy) Url(prefix, name string) string {
|
|
||||||
if name == "" {
|
|
||||||
return prefix + "/api/policy"
|
|
||||||
} else {
|
|
||||||
return prefix + "/api/policy/" + name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Policy) Tmpl() string {
|
|
||||||
return `# total {{ len . }}
|
|
||||||
{{ps -16 "name"}} {{ ps -20 "source" }} {{ ps -20 "destination" }}
|
|
||||||
{{- range . }}
|
|
||||||
{{ps -16 .Name}} {{ ps -20 .Source }} {{ ps -20 .Dest }}
|
|
||||||
{{- end }}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Policy) List(c *cli.Context) error {
|
|
||||||
url := u.Url(c.String("url"), "")
|
|
||||||
clt := u.NewHttp(c.String("token"))
|
|
||||||
var items []schema.EspPolicy
|
|
||||||
if err := clt.GetJSON(url, &items); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sort.SliceStable(items, func(i, j int) bool {
|
|
||||||
ii := items[i]
|
|
||||||
jj := items[j]
|
|
||||||
return ii.Name+ii.Source > jj.Name+jj.Source
|
|
||||||
})
|
|
||||||
return u.Out(items, c.String("format"), u.Tmpl())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u Policy) Commands(app *api.App) {
|
|
||||||
app.Command(&cli.Command{
|
|
||||||
Name: "policy",
|
|
||||||
Aliases: []string{"po"},
|
|
||||||
Usage: "IPSec policy configuration",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "list",
|
|
||||||
Usage: "Display all xfrm policy",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Action: u.List,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
package v5
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/luscis/openlan/cmd/api"
|
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
type State struct {
|
|
||||||
Cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u State) Url(prefix, name string) string {
|
|
||||||
if name == "" {
|
|
||||||
return prefix + "/api/state"
|
|
||||||
} else {
|
|
||||||
return prefix + "/api/state/" + name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u State) Tmpl() string {
|
|
||||||
return `# total {{ len . }}
|
|
||||||
{{ps -16 "name"}} {{ps -8 "spi"}} {{ ps -16 "local" }} {{ ps -16 "remote" }} {{ ps -12 "rx bytes" }} {{ ps -12 "tx bytes" }} {{ ps -12 "rx packages" }} {{ ps -12 "tx packages" }}
|
|
||||||
{{- range . }}
|
|
||||||
{{ps -16 .Name}} {{pi -8 .Spi }} {{ ps -16 .Local }} {{ ps -16 .Remote }} {{ pi -12 .RxBytes }} {{ pi -12 .TxBytes }} {{ pi -12 .RxPackages }} {{ pi -12 .TxPackages }}
|
|
||||||
{{- end }}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u State) List(c *cli.Context) error {
|
|
||||||
url := u.Url(c.String("url"), "")
|
|
||||||
clt := u.NewHttp(c.String("token"))
|
|
||||||
var items []schema.EspState
|
|
||||||
if err := clt.GetJSON(url, &items); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sort.SliceStable(items, func(i, j int) bool {
|
|
||||||
ii := items[i]
|
|
||||||
jj := items[j]
|
|
||||||
return ii.Spi > jj.Spi
|
|
||||||
})
|
|
||||||
return u.Out(items, c.String("format"), u.Tmpl())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u State) Commands(app *api.App) {
|
|
||||||
app.Command(&cli.Command{
|
|
||||||
Name: "state",
|
|
||||||
Aliases: []string{"se"},
|
|
||||||
Usage: "IPSec state configuration",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
{
|
|
||||||
Name: "list",
|
|
||||||
Usage: "Display all xfrm state",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Action: u.List,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@@ -1,200 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
db "github.com/luscis/openlan/pkg/database"
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
UdpPort int
|
|
||||||
LogLevel int
|
|
||||||
LogFile string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Parse() {
|
|
||||||
flag.IntVar(&c.UdpPort, "port", 4500, "UDP port listen on")
|
|
||||||
flag.StringVar(&c.LogFile, "log:file", "/dev/null", "File log saved to")
|
|
||||||
flag.IntVar(&c.LogLevel, "log:level", 20, "Log level value")
|
|
||||||
flag.Parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
type UdpServer struct {
|
|
||||||
stop chan struct{}
|
|
||||||
out *libol.SubLogger
|
|
||||||
server *libol.UdpInServer
|
|
||||||
cfg *Config
|
|
||||||
links *libol.SafeStrMap
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUdpServer(cfg *Config) *UdpServer {
|
|
||||||
c := &UdpServer{
|
|
||||||
out: libol.NewSubLogger("udp"),
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
cfg: cfg,
|
|
||||||
links: libol.NewSafeStrMap(128),
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) Initialize() {
|
|
||||||
u.server = &libol.UdpInServer{
|
|
||||||
Port: uint16(u.cfg.UdpPort),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) Start() {
|
|
||||||
u.out.Info("UdpServer.Start on %d", u.server.Port)
|
|
||||||
if err := u.server.Open(); err != nil {
|
|
||||||
u.out.Error("UdpServer.Start open socket %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) Stop() {
|
|
||||||
u.out.Info("UdpServer.Stop on %d", u.server.Port)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) Device2UUID(value string) string {
|
|
||||||
if link := u.links.Get(value); link != nil {
|
|
||||||
if older, ok := link.(*db.VirtualLink); ok {
|
|
||||||
return older.UUID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) toStatus(li *db.DBClient, from *libol.UdpInConnection) {
|
|
||||||
device := fmt.Sprintf("spi:%d", from.Spi)
|
|
||||||
obj := &db.VirtualLink{
|
|
||||||
UUID: u.Device2UUID(device),
|
|
||||||
}
|
|
||||||
if err := li.Client.Get(obj); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if obj.Status == nil {
|
|
||||||
obj.Status = make(map[string]string, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
new_conn := fmt.Sprintf("udp:%s", from.Connection())
|
|
||||||
if obj.Status["remote_connection"] != new_conn ||
|
|
||||||
obj.Status["hostname"] != from.Hostname {
|
|
||||||
obj.Status["remote_connection"] = new_conn
|
|
||||||
obj.Status["hostname"] = from.Hostname
|
|
||||||
u.out.Info("Updating %s on %s from %s", device, new_conn, from.Hostname)
|
|
||||||
}
|
|
||||||
// Updating status
|
|
||||||
obj.Status["update_at"] = time.Now().UTC().String()
|
|
||||||
ops, err := li.Client.Where(obj).Update(obj)
|
|
||||||
if err != nil {
|
|
||||||
u.out.Warn("UdpServer.toStatus update %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err := li.Client.Transact(ops...); err != nil {
|
|
||||||
u.out.Warn("UdpServer.toStatus commit %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reply pong
|
|
||||||
if obj.Connection == "any" {
|
|
||||||
_ = u.server.Send(from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) toLinkState(li *db.DBClient, from *libol.UdpInConnection) {
|
|
||||||
device := fmt.Sprintf("spi:%d", from.Spi)
|
|
||||||
obj := &db.VirtualLink{
|
|
||||||
UUID: u.Device2UUID(device),
|
|
||||||
}
|
|
||||||
if err := li.Client.Get(obj); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if obj.LinkState != "up" {
|
|
||||||
obj.LinkState = "up"
|
|
||||||
ops, err := li.Client.Where(obj).Update(obj)
|
|
||||||
if err != nil {
|
|
||||||
u.out.Warn("UdpServer.toLinkState update %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err := li.Client.Transact(ops...); err != nil {
|
|
||||||
u.out.Warn("UdpServer.toLinkState commit %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO check update_at and update to down if expired.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) Pong() {
|
|
||||||
li, err := db.NewClient(nil)
|
|
||||||
if err != nil {
|
|
||||||
u.out.Error("UdpServer.Pong open db with %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
from, _ := u.server.Recv()
|
|
||||||
u.out.Cmd("UdpServer.Pong received %s", from.String())
|
|
||||||
|
|
||||||
u.toStatus(li, from)
|
|
||||||
u.toLinkState(li, from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) toPing(li *db.DBClient, obj *db.VirtualLink) {
|
|
||||||
addr, port := db.GetAddrPort(obj.Connection[4:])
|
|
||||||
if port == 0 {
|
|
||||||
port = 4500
|
|
||||||
}
|
|
||||||
conn := &libol.UdpInConnection{
|
|
||||||
Spi: obj.Spi(),
|
|
||||||
RemotePort: uint16(port),
|
|
||||||
RemoteAddr: addr,
|
|
||||||
}
|
|
||||||
u.out.Cmd("UdpServer.toPing send to %s", conn.String())
|
|
||||||
_ = u.server.Send(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpServer) Ping() {
|
|
||||||
li, err := db.NewClient(nil)
|
|
||||||
if err != nil {
|
|
||||||
u.out.Error("UdpServer.Ping open db with %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
var ls []db.VirtualLink
|
|
||||||
_ = li.Client.List(&ls)
|
|
||||||
u.links.Clear()
|
|
||||||
for i := range ls {
|
|
||||||
obj := &ls[i]
|
|
||||||
if err := u.links.Mod(obj.Device, obj); err != nil {
|
|
||||||
u.out.Error("UdpServer.Ping %s", err)
|
|
||||||
}
|
|
||||||
if !obj.IsUdpIn() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
u.toPing(li, obj)
|
|
||||||
}
|
|
||||||
time.Sleep(10 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
c := &Config{}
|
|
||||||
c.Parse()
|
|
||||||
|
|
||||||
libol.SetLogger(c.LogFile, c.LogLevel)
|
|
||||||
|
|
||||||
srv := NewUdpServer(c)
|
|
||||||
srv.Initialize()
|
|
||||||
|
|
||||||
srv.Start()
|
|
||||||
libol.Go(srv.Ping)
|
|
||||||
libol.Go(srv.Pong)
|
|
||||||
|
|
||||||
libol.Wait()
|
|
||||||
srv.Stop()
|
|
||||||
}
|
|
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/luscis/openlan/cmd/api"
|
|
||||||
"github.com/luscis/openlan/pkg/cache"
|
"github.com/luscis/openlan/pkg/cache"
|
||||||
"github.com/luscis/openlan/pkg/config"
|
"github.com/luscis/openlan/pkg/config"
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
"github.com/luscis/openlan/pkg/libol"
|
||||||
@@ -12,9 +11,6 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
udp := api.GetEnv("ESPUDP", "4500")
|
|
||||||
|
|
||||||
config.SetLocalUdp(udp)
|
|
||||||
c := config.NewSwitch()
|
c := config.NewSwitch()
|
||||||
config.Update(c)
|
config.Update(c)
|
||||||
|
|
||||||
|
30
dist/rootfs/etc/openlan/switch/l2tp-psk.conf
vendored
30
dist/rootfs/etc/openlan/switch/l2tp-psk.conf
vendored
@@ -1,30 +0,0 @@
|
|||||||
conn L2TP-PSK
|
|
||||||
#
|
|
||||||
# Configuration for one user with any type of IPsec/L2TP client
|
|
||||||
# including the updated Windows 2000/XP (MS KB Q818043), but
|
|
||||||
# excluding the non-updated Windows 2000/XP.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Use a Preshared Key. Disable Perfect Forward Secrecy.
|
|
||||||
#
|
|
||||||
authby=secret
|
|
||||||
pfs=no
|
|
||||||
#
|
|
||||||
left=123.123.123.123
|
|
||||||
#
|
|
||||||
leftprotoport=17/1701
|
|
||||||
#
|
|
||||||
# The remote user.
|
|
||||||
#
|
|
||||||
right=%any
|
|
||||||
rightprotoport=17/%any
|
|
||||||
rightsubnet=vhost:%priv,%no
|
|
||||||
#
|
|
||||||
# Change 'ignore' to 'add' to enable the configuration for this user.
|
|
||||||
#
|
|
||||||
auto=ignore
|
|
||||||
keyingtries=3
|
|
||||||
# Only the mast stack with Openswan supports SAref tracking with
|
|
||||||
# overlapping IP address support
|
|
||||||
overlapip=yes
|
|
||||||
sareftrack=yes
|
|
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "fabric",
|
|
||||||
"provider": "fabric",
|
|
||||||
"bridge": {
|
|
||||||
"name": "br-tun"
|
|
||||||
},
|
|
||||||
"specifies": {
|
|
||||||
"tcpMss": 1332,
|
|
||||||
"tunnels": [
|
|
||||||
{
|
|
||||||
"remote": "100.64.0.20"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"remote": "100.64.0.21"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"remote": "100.64.0.33"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ipsec",
|
|
||||||
"provider": "esp"
|
|
||||||
}
|
|
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ipsec",
|
|
||||||
"provider": "esp",
|
|
||||||
"specifies": {
|
|
||||||
"address": "100.64.0.10",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"spi": 300,
|
|
||||||
"peer": "100.64.0.30",
|
|
||||||
"state": {
|
|
||||||
"auth": "a263d01a96db11eb9",
|
|
||||||
"crypt": "9b73bc48e3864b3ebc"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"spi": 100,
|
|
||||||
"peer": "100.64.0.20",
|
|
||||||
"state": {
|
|
||||||
"remote": "2.16.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"spi": 200,
|
|
||||||
"address": "100.64.0.11",
|
|
||||||
"peer": "100.64.0.30",
|
|
||||||
"state": {
|
|
||||||
"local": "192.168.1.10",
|
|
||||||
"remote": "2.16.1.2",
|
|
||||||
"auth": "a263d01a96db11eb9",
|
|
||||||
"crypt": "9b73bc48e3864b3ebc"
|
|
||||||
},
|
|
||||||
"policies": [
|
|
||||||
{
|
|
||||||
"source": "192.168.1.0/24",
|
|
||||||
"destination": "192.168.2.0/24"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@@ -13,5 +13,11 @@
|
|||||||
{
|
{
|
||||||
"segment": 23,
|
"segment": 23,
|
||||||
"remote": "enp2s2"
|
"remote": "enp2s2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"segment": 44,
|
||||||
|
"remote": "3.3.3.6",
|
||||||
|
"protocol": "vxlan",
|
||||||
|
"secret": "swordfish"
|
||||||
}
|
}
|
||||||
]
|
]
|
@@ -15,17 +15,5 @@
|
|||||||
"baseDN": "dc=openlan,dc=com",
|
"baseDN": "dc=openlan,dc=com",
|
||||||
"attribute": "cn",
|
"attribute": "cn",
|
||||||
"filter": "(cn=%s)"
|
"filter": "(cn=%s)"
|
||||||
},
|
|
||||||
"l2tp": {
|
|
||||||
"ipsec": "enable",
|
|
||||||
"address": "192.168.33.1",
|
|
||||||
"subnet": {
|
|
||||||
"startAt": "192.168.33.100",
|
|
||||||
"endAt": "192.168.33.250"
|
|
||||||
},
|
|
||||||
"options": [
|
|
||||||
"ms-dns 8.8.8.8",
|
|
||||||
"ms-dns 8.8.4.4"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
61
dist/rootfs/var/openlan/script/confd.sh
vendored
61
dist/rootfs/var/openlan/script/confd.sh
vendored
@@ -1,61 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
command=$1; shift
|
|
||||||
options=$@;
|
|
||||||
|
|
||||||
dir=$(dirname $0)
|
|
||||||
|
|
||||||
OVSDB_SERVER_BIN="/usr/bin/env ovsdb-server"
|
|
||||||
OVSDB_TOOL_BIN="/usr/bin/env ovsdb-tool"
|
|
||||||
[ "$OVSDB_DATABASE_SCH" == "" ] && OVSDB_DATABASE_SCH="/var/openlan/confd.schema.json"
|
|
||||||
[ "$OVSDB_DATABASE" == "" ] && OVSDB_DATABASE="/etc/openlan/switch/confd.db"
|
|
||||||
[ "$OVSDB_LOG_FILE" == "" ] && OVSDB_LOG_FILE="/var/openlan/confd/confd.log"
|
|
||||||
[ "$OVSDB_SOCK" == "" ] && OVSDB_SOCK="/var/openlan/confd/confd.sock"
|
|
||||||
[ "$OVSDB_PID_FILE" == "" ] && OVSDB_PID_FILE="/var/openlan/confd/confd.pid"
|
|
||||||
|
|
||||||
mkdir -p /var/openlan/confd
|
|
||||||
|
|
||||||
function stop() {
|
|
||||||
[ -e "$OVSDB_PID_FILE" ] && kill "$(cat $OVSDB_PID_FILE)"
|
|
||||||
}
|
|
||||||
|
|
||||||
## Upgrade database.
|
|
||||||
# ovsdb-client convert unix:///var/openlan/confd/confd.sock /var/openlan/confd.schema.json
|
|
||||||
|
|
||||||
function start() {
|
|
||||||
[ -e "$OVSDB_DATABASE" ] || {
|
|
||||||
$OVSDB_TOOL_BIN create $OVSDB_DATABASE $OVSDB_DATABASE_SCH
|
|
||||||
}
|
|
||||||
|
|
||||||
set +x
|
|
||||||
set $OVSDB_SERVER_BIN $OVSDB_DATABASE
|
|
||||||
set "$@" -vconsole:info -vsyslog:off -vfile:off
|
|
||||||
set "$@" --remote=punix:"$OVSDB_SOCK"
|
|
||||||
set "$@" --log-file="$OVSDB_LOG_FILE"
|
|
||||||
set "$@" --pidfile="$OVSDB_PID_FILE"
|
|
||||||
[ "$OVSDB_OPTIONS" != "" ] && set "$@" $OVSDB_OPTIONS
|
|
||||||
for opt in $options; do
|
|
||||||
set "$@" $opt
|
|
||||||
done
|
|
||||||
set -x
|
|
||||||
export OVS_RUNDIR="/var/openlan/confd"
|
|
||||||
exec "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
case $command in
|
|
||||||
start)
|
|
||||||
start
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
stop
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
restart
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo >&2 "$0: unknown command \"$command\" (start/stop/restart)"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
7
dist/rootfs/var/openlan/script/install.sh
vendored
7
dist/rootfs/var/openlan/script/install.sh
vendored
@@ -28,10 +28,10 @@ function requires() {
|
|||||||
echo "Install dependents ..."
|
echo "Install dependents ..."
|
||||||
if [ "$OS"x == "centos"x ]; then
|
if [ "$OS"x == "centos"x ]; then
|
||||||
yum install -y openssl net-tools iptables iputils iperf3 tcpdump
|
yum install -y openssl net-tools iptables iputils iperf3 tcpdump
|
||||||
yum install -y openvpn openvswitch dnsmasq bridge-utils ipset
|
yum install -y openvpn dnsmasq bridge-utils ipset libreswan procps
|
||||||
elif [ "$OS"x == "ubuntu"x ]; then
|
elif [ "$OS"x == "ubuntu"x ]; then
|
||||||
apt-get install -y net-tools iptables iproute2 tcpdump ca-certificates iperf3
|
apt-get install -y net-tools iptables iproute2 tcpdump ca-certificates iperf3
|
||||||
apt-get install -y openvpn openvswitch-switch dnsmasq bridge-utils ipset
|
apt-get install -y openvpn dnsmasq bridge-utils ipset libreswan procps
|
||||||
else
|
else
|
||||||
echo "We didn't find any packet tool: $OS"
|
echo "We didn't find any packet tool: $OS"
|
||||||
fi
|
fi
|
||||||
@@ -42,6 +42,7 @@ function install() {
|
|||||||
local source=$(find $tmp -maxdepth 1 -name 'openlan-*')
|
local source=$(find $tmp -maxdepth 1 -name 'openlan-*')
|
||||||
cd $source && {
|
cd $source && {
|
||||||
/usr/bin/env \cp -rf ./{etc,usr,var} /
|
/usr/bin/env \cp -rf ./{etc,usr,var} /
|
||||||
|
chmod +x /var/openlan/script/*.sh
|
||||||
/usr/bin/env find ./ -type f > /usr/share/openlan.db
|
/usr/bin/env find ./ -type f > /usr/share/openlan.db
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,6 +69,8 @@ function post() {
|
|||||||
cp -rf /var/openlan/cert/ca.crt /usr/local/share/ca-certificates/OpenLAN_CA.crt
|
cp -rf /var/openlan/cert/ca.crt /usr/local/share/ca-certificates/OpenLAN_CA.crt
|
||||||
update-ca-certificates
|
update-ca-certificates
|
||||||
fi
|
fi
|
||||||
|
## Initialize NSS database
|
||||||
|
certutil -N -d sql:/var/lib/ipsec/nss --empty-password
|
||||||
}
|
}
|
||||||
|
|
||||||
function finish() {
|
function finish() {
|
||||||
|
9
dist/rootfs/var/openlan/script/ipsec.sh
vendored
Normal file
9
dist/rootfs/var/openlan/script/ipsec.sh
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
/sbin/ip xfrm policy flush
|
||||||
|
/sbin/ip xfrm state flush
|
||||||
|
|
||||||
|
/usr/libexec/ipsec/addconn --config /etc/ipsec.conf --checkconfig
|
||||||
|
/usr/libexec/ipsec/pluto --leak-detective --config /etc/ipsec.conf --nofork
|
10
dist/rootfs/var/openlan/script/task.sh
vendored
10
dist/rootfs/var/openlan/script/task.sh
vendored
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export VERSION=v6
|
|
||||||
while true; do
|
|
||||||
names=$(openlan na ls | grep -w 'name:' | sed 's/name://g')
|
|
||||||
for name in $names; do
|
|
||||||
openlan name add --name $name
|
|
||||||
done
|
|
||||||
sleep 5
|
|
||||||
done
|
|
18
dist/rootfs/var/openlan/script/update.sh
vendored
18
dist/rootfs/var/openlan/script/update.sh
vendored
@@ -1,18 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
## Upgrade ovsdb
|
|
||||||
# ovsdb-client convert unix:///var/openlan/confd/confd.sock /var/openlan/confd.schema.json
|
|
||||||
|
|
||||||
## Enable check for DDNS
|
|
||||||
# [root@centos ~]# crontab -l
|
|
||||||
# 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /var/openlan/script/update.sh
|
|
||||||
# [root@centos ~]#
|
|
||||||
|
|
||||||
## Update your DDNS
|
|
||||||
export VERSION=v6
|
|
||||||
names=$(openlan na ls | grep -w 'name:' | sed 's/name://g')
|
|
||||||
for name in $names; do
|
|
||||||
openlan name add --name $name
|
|
||||||
done
|
|
@@ -1,78 +0,0 @@
|
|||||||
version: "2.3"
|
|
||||||
services:
|
|
||||||
confd:
|
|
||||||
restart: always
|
|
||||||
image: "luscis/openlan:latest.x86_64"
|
|
||||||
privileged: true
|
|
||||||
entrypoint: ["/var/openlan/script/confd.sh", "start"]
|
|
||||||
network_mode: "host"
|
|
||||||
volumes:
|
|
||||||
- /opt/openlan/confd:/var/openlan/confd
|
|
||||||
- /opt/openlan/etc/openlan:/etc/openlan
|
|
||||||
ovsdb-server:
|
|
||||||
restart: always
|
|
||||||
image: "luscis/openlan:latest.x86_64"
|
|
||||||
privileged: true
|
|
||||||
entrypoint: ["/var/openlan/script/ovsdb-server.sh", "start"]
|
|
||||||
network_mode: service:confd
|
|
||||||
volumes:
|
|
||||||
- /opt/openlan/run/openvswitch:/run/openvswitch
|
|
||||||
- /opt/openlan/etc/openvswitch:/etc/openvswitch
|
|
||||||
depends_on:
|
|
||||||
- confd
|
|
||||||
ovs-vswitchd:
|
|
||||||
restart: always
|
|
||||||
image: "luscis/openlan:latest.x86_64"
|
|
||||||
privileged: true
|
|
||||||
network_mode: service:confd
|
|
||||||
entrypoint: ["/var/openlan/script/ovs-vswitchd.sh", "start"]
|
|
||||||
volumes:
|
|
||||||
- /opt/openlan/run/openvswitch:/run/openvswitch
|
|
||||||
depends_on:
|
|
||||||
- confd
|
|
||||||
- ovsdb-server
|
|
||||||
switch:
|
|
||||||
restart: always
|
|
||||||
image: "luscis/openlan:latest.x86_64"
|
|
||||||
privileged: true
|
|
||||||
network_mode: service:confd
|
|
||||||
entrypoint: ["/var/openlan/script/switch.sh", "start"]
|
|
||||||
# stop_grace_period: 30s
|
|
||||||
# environment:
|
|
||||||
# - ESPUDP=4600
|
|
||||||
volumes:
|
|
||||||
- /opt/openlan/confd:/var/openlan/confd
|
|
||||||
- /opt/openlan/run/openvswitch:/run/openvswitch
|
|
||||||
- /opt/openlan/etc/openvswitch:/etc/openvswitch
|
|
||||||
- /opt/openlan/etc/openlan:/etc/openlan
|
|
||||||
depends_on:
|
|
||||||
- confd
|
|
||||||
- ovsdb-server
|
|
||||||
- ovs-vswitchd
|
|
||||||
proxy:
|
|
||||||
restart: always
|
|
||||||
image: "luscis/openlan:latest.x86_64"
|
|
||||||
network_mode: service:confd
|
|
||||||
entrypoint: ["/usr/bin/openlan-proxy", "-conf", "/etc/openlan/proxy.json", "-log:file", "/dev/null"]
|
|
||||||
volumes:
|
|
||||||
- /opt/openlan/etc/openlan:/etc/openlan
|
|
||||||
depends_on:
|
|
||||||
- confd
|
|
||||||
- switch
|
|
||||||
task:
|
|
||||||
restart: always
|
|
||||||
image: "luscis/openlan:latest.x86_64"
|
|
||||||
network_mode: service:confd
|
|
||||||
entrypoint: ["/var/openlan/script/task.sh"]
|
|
||||||
volumes:
|
|
||||||
- /opt/openlan/confd:/var/openlan/confd
|
|
||||||
- /opt/openlan/run/openvswitch:/run/openvswitch
|
|
||||||
- /opt/openlan/etc/openvswitch:/etc/openvswitch
|
|
||||||
- /opt/openlan/etc/openlan:/etc/openlan
|
|
||||||
depends_on:
|
|
||||||
- confd
|
|
||||||
- switch
|
|
||||||
expoter:
|
|
||||||
restart: always
|
|
||||||
image: "prom/node-exporter:v1.7.0"
|
|
||||||
network_mode: service:confd
|
|
@@ -1,5 +1,13 @@
|
|||||||
version: "2.3"
|
version: "2.3"
|
||||||
services:
|
services:
|
||||||
|
ipsec:
|
||||||
|
restart: always
|
||||||
|
image: "luscis/openlan:latest.x86_64"
|
||||||
|
privileged: true
|
||||||
|
network_mode: host
|
||||||
|
entrypoint: ["/var/openlan/script/ipsec.sh"]
|
||||||
|
volumes:
|
||||||
|
- /opt/openlan/etc/ipsecd.d:/etc/ipsec.d
|
||||||
switch:
|
switch:
|
||||||
restart: always
|
restart: always
|
||||||
image: "luscis/openlan:latest.x86_64"
|
image: "luscis/openlan:latest.x86_64"
|
||||||
@@ -8,6 +16,9 @@ services:
|
|||||||
entrypoint: ["/var/openlan/script/switch.sh", "start"]
|
entrypoint: ["/var/openlan/script/switch.sh", "start"]
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/openlan/etc/openlan:/etc/openlan
|
- /opt/openlan/etc/openlan:/etc/openlan
|
||||||
|
- /opt/openlan/etc/ipsecd.d:/etc/ipsec.d
|
||||||
|
depends_on:
|
||||||
|
- ipsec
|
||||||
proxy:
|
proxy:
|
||||||
restart: always
|
restart: always
|
||||||
image: "luscis/openlan:latest.x86_64"
|
image: "luscis/openlan:latest.x86_64"
|
||||||
@@ -17,3 +28,7 @@ services:
|
|||||||
- /opt/openlan/etc/openlan:/etc/openlan
|
- /opt/openlan/etc/openlan:/etc/openlan
|
||||||
depends_on:
|
depends_on:
|
||||||
- switch
|
- switch
|
||||||
|
exporter:
|
||||||
|
restart: always
|
||||||
|
image: "prom/node-exporter:v1.7.0"
|
||||||
|
network_mode: host
|
299
docs/fabric.md
299
docs/fabric.md
@@ -1,299 +0,0 @@
|
|||||||
# Setup Fabric Network
|
|
||||||
We using 192.168.100.0/24 to emulate a internet network. And underlay: 100.65.0.0/24 over Internet by IPSec: SPI-117118/117119/118119.
|
|
||||||
```
|
|
||||||
192.168.100.117
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
+---------+
|
|
||||||
| dev-117 |
|
|
||||||
+---------+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
SPI-117118 / \ SPI-117119
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
+---------+ +---------+
|
|
||||||
| dev-118 | ------------ | kvm-119 |
|
|
||||||
+---------+ +---------+
|
|
||||||
| |
|
|
||||||
| SPI-118119 |
|
|
||||||
| |
|
|
||||||
192.168.100.118 192.168.100.119
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Data Center Interconnect with Subnet 192.168.30-40.0/24 Over IPSec network: 100.65.0.0/24 by VxLAN/STT.
|
|
||||||
```
|
|
||||||
|
|
||||||
100.65.0.117
|
|
||||||
|
|
|
||||||
eth1.200 --- | --- eth1.100
|
|
||||||
\ | /
|
|
||||||
+---------+
|
|
||||||
| dev-117 |
|
|
||||||
+---------+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
enp2s4.100 --- / \ --- eth4.30
|
|
||||||
\ / \ /
|
|
||||||
+---------+ +---------+
|
|
||||||
| dev-118 | ------------- | kvm-119 |
|
|
||||||
+---------+ +---------+
|
|
||||||
/ | | \
|
|
||||||
enp2s4.101 --- | | --- eth4.200
|
|
||||||
| |
|
|
||||||
100.65.0.118 100.65.0.119
|
|
||||||
|
|
||||||
|
|
||||||
VNI-1023 192.168.30.0/24 [dev-117_eth1.100, dev-118_enp2s4.100, kvm-119_eth4.30]
|
|
||||||
VNI-1024 192.168.40.0/24 [dev-117_eth1.200, dev-118_enp2s4.101, kvm-119_eth4.200]
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Install Software
|
|
||||||
```
|
|
||||||
[root@dev-117 network]# yum install -y epel-release
|
|
||||||
[root@dev-117 network]# yum install -y centos-release-openstack-train
|
|
||||||
[root@dev-117 network]# yum install -y libibverbs bridge-utils iproute openvswitch
|
|
||||||
[root@dev-117 network]#
|
|
||||||
[root@dev-117 network]# systemctl enable --now openvswitch
|
|
||||||
[root@dev-117 network]# ovs-vsctl show
|
|
||||||
6bea41ef-b177-4e5c-81b4-fe1f8b90cbac
|
|
||||||
Bridge br-tun
|
|
||||||
fail_mode: secure
|
|
||||||
Port "vx-100650118"
|
|
||||||
Interface "vx-100650118"
|
|
||||||
type: vxlan
|
|
||||||
options: {df_default="false", dst_port="4789", key=flow, remote_ip="100.65.0.118"}
|
|
||||||
Port "vnt-3ff"
|
|
||||||
Interface "vnt-3ff"
|
|
||||||
Port br-tun
|
|
||||||
Interface br-tun
|
|
||||||
type: internal
|
|
||||||
Port "vx-100650117"
|
|
||||||
Interface "vx-100650119"
|
|
||||||
type: vxlan
|
|
||||||
options: {df_default="false", dst_port="4789", key=flow, remote_ip="100.65.0.119"}
|
|
||||||
Port "vnt-400"
|
|
||||||
Interface "vnt-400"
|
|
||||||
ovs_version: "2.12.0"
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration on Node: dev-117
|
|
||||||
```
|
|
||||||
[root@dev-117 network]# cat ./esp.json
|
|
||||||
{
|
|
||||||
"name": "esp",
|
|
||||||
"provider": "esp",
|
|
||||||
"specifies": {
|
|
||||||
"address": "100.65.0.117",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"peer": "100.65.0.118",
|
|
||||||
"spi": 117118,
|
|
||||||
"state": {
|
|
||||||
"remote": "192.168.100.118"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"peer": "100.65.0.119",
|
|
||||||
"spi": 117119,
|
|
||||||
"state": {
|
|
||||||
"remote": "192.168.100.119"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[root@dev-117 network]#
|
|
||||||
[root@dev-117 network]# cat ./fabric.json
|
|
||||||
{
|
|
||||||
"name": "fabric",
|
|
||||||
"provider": "fabric",
|
|
||||||
"bridge": {
|
|
||||||
"name": "br-tun"
|
|
||||||
},
|
|
||||||
"specifies": {
|
|
||||||
"mss": 1332,
|
|
||||||
"tunnels": [
|
|
||||||
{
|
|
||||||
"dport": 4789,
|
|
||||||
"remote": "100.65.0.118"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dport": 4789,
|
|
||||||
"remote": "100.65.0.119"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"networks": [
|
|
||||||
{
|
|
||||||
"vni": 1023,
|
|
||||||
"bridge": "br-100",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"vlan": 100,
|
|
||||||
"interface": "eth1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"vni": 1024,
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"vlan": 200,
|
|
||||||
"interface": "eth1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[root@dev-117 network]#
|
|
||||||
[root@dev-117 network]# ip route
|
|
||||||
100.65.0.118 via 100.65.0.117 dev spi117118
|
|
||||||
100.65.0.119 via 100.65.0.117 dev spi117119
|
|
||||||
192.168.30.0/24 dev br-100 proto kernel scope link src 192.168.30.117
|
|
||||||
192.168.40.0/24 dev br-400 proto kernel scope link src 192.168.40.117
|
|
||||||
192.168.100.0/24 dev eth2 proto kernel scope link src 192.168.100.117
|
|
||||||
[root@dev-117 network]#
|
|
||||||
[root@dev-117 network]#
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration on Node: dev-118
|
|
||||||
```
|
|
||||||
[root@dev-118 network]# cat ./fabric.json
|
|
||||||
{
|
|
||||||
"name": "fabric",
|
|
||||||
"provider": "fabric",
|
|
||||||
"bridge": {
|
|
||||||
"name": "br-tun"
|
|
||||||
},
|
|
||||||
"specifies": {
|
|
||||||
"tunnels": [
|
|
||||||
{
|
|
||||||
"remote": "100.65.0.117"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"remote": "100.65.0.119"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"networks": [
|
|
||||||
{
|
|
||||||
"vni": 1023,
|
|
||||||
"bridge": "br-100",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"vlan": 100,
|
|
||||||
"interface": "enp2s4"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"vni": 1024,
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"vlan": 101,
|
|
||||||
"interface": "enp2s4"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[root@dev-118 network]#
|
|
||||||
[root@dev-118 network]# ip route
|
|
||||||
100.65.0.117 via 100.65.0.118 dev spi117118
|
|
||||||
100.65.0.119 via 100.65.0.118 dev spi118119
|
|
||||||
192.168.30.0/24 dev br-100 proto kernel scope link src 192.168.30.118
|
|
||||||
192.168.40.0/24 dev br-400 proto kernel scope link src 192.168.40.118
|
|
||||||
192.168.100.0/24 dev enp2s3 proto kernel scope link src 192.168.100.118 metric 101
|
|
||||||
[root@dev-118 network]#
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration on Node: kvm-119
|
|
||||||
```
|
|
||||||
[root@kvm-119 switch]# cat ./network/esp.json
|
|
||||||
{
|
|
||||||
"name": "esp",
|
|
||||||
"provider": "esp",
|
|
||||||
"specifies": {
|
|
||||||
"address": "100.65.0.119",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"peer": "100.65.0.117",
|
|
||||||
"spi": 117119,
|
|
||||||
"state": {
|
|
||||||
"remote": "192.168.100.117"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"peer": "100.65.0.118",
|
|
||||||
"spi": 118119,
|
|
||||||
"state": {
|
|
||||||
"remote": "192.168.100.118"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[root@kvm-119 switch]#
|
|
||||||
[root@kvm-119 switch]# cat ./network/fabric.json
|
|
||||||
{
|
|
||||||
"name": "fabric",
|
|
||||||
"provider": "fabric",
|
|
||||||
"bridge": {
|
|
||||||
"name": "br-tun"
|
|
||||||
},
|
|
||||||
"specifies": {
|
|
||||||
"tunnels": [
|
|
||||||
{
|
|
||||||
"dport": 4789,
|
|
||||||
"remote": "100.65.0.117"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dport": 4789,
|
|
||||||
"remote": "100.65.0.118"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"networks": [
|
|
||||||
{
|
|
||||||
"vni": 1023,
|
|
||||||
"bridge": "br-100",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"vlan": 30,
|
|
||||||
"interface": "eth4"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"vni": 1024,
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"vlan": 200,
|
|
||||||
"interface": "eth4"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[root@kvm-119 switch]#
|
|
||||||
[root@kvm-119 switch]# ip route
|
|
||||||
100.65.0.117 via 100.65.0.119 dev spi117119
|
|
||||||
100.65.0.118 via 100.65.0.119 dev spi118119
|
|
||||||
192.168.30.0/24 dev br-100 proto kernel scope link src 192.168.30.119
|
|
||||||
192.168.40.0/24 dev br-400 proto kernel scope link src 192.168.40.119
|
|
||||||
192.168.100.0/24 dev eth1 proto kernel scope link src 192.168.100.119
|
|
||||||
[root@kvm-119 switch]#
|
|
||||||
```
|
|
@@ -1,58 +0,0 @@
|
|||||||
Topology
|
|
||||||
========
|
|
||||||
We use 192.168.7.0/24 as underlay network for IPSec. And S1 has public address with 192.168.7.11, C1 and C2 under firewall without public address.
|
|
||||||
|
|
||||||
+----+
|
|
||||||
| s1 | -- .10.1/24
|
|
||||||
+----+
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
/ \
|
|
||||||
+----+ +----+
|
|
||||||
192.168.2.0/24 -- | c2 | | c3 | -- 192.168.3.0/24
|
|
||||||
+----+ +----+
|
|
||||||
| |
|
|
||||||
.10.2/32 .10.3/32
|
|
||||||
|
|
||||||
Server
|
|
||||||
======
|
|
||||||
```
|
|
||||||
$ openlan network add --name ipsec --provider esp --address 10.10.10.1/24
|
|
||||||
$ openlan link add --network ipsec --device spi:12 --remote-address 10.10.10.2
|
|
||||||
$ openlan link add --network ipsec --device spi:13 --remote-address 10.10.10.3
|
|
||||||
```
|
|
||||||
```
|
|
||||||
$ openlan route add --network ipsec --prefix 192.168.2.0/24 --gateway spi:12
|
|
||||||
$ openlan route add --network ipsec --prefix 192.168.3.0/24 --gateway spi:13
|
|
||||||
```
|
|
||||||
|
|
||||||
Client
|
|
||||||
======
|
|
||||||
|
|
||||||
C2
|
|
||||||
--
|
|
||||||
```
|
|
||||||
$ openlan network add --name ipsec --provider esp --address 10.10.10.2
|
|
||||||
$ openlan link add --network ipsec --connection udp:192.168.7.11 --device spi:12 --remote-address 10.10.10.1/24
|
|
||||||
$ openlan link ls
|
|
||||||
```
|
|
||||||
```
|
|
||||||
$ ping 10.10.10.1
|
|
||||||
```
|
|
||||||
```
|
|
||||||
$ openlan route add --network ipsec --prefix 192.168.3.0/24 --gateway spi:12
|
|
||||||
```
|
|
||||||
|
|
||||||
C3
|
|
||||||
--
|
|
||||||
|
|
||||||
```
|
|
||||||
$ openlan network add --name ipsec --provider esp --address 10.10.10.3
|
|
||||||
$ openlan link add --network ipsec --connection udp:192.168.7.11 --device spi:13 --remote-address 10.10.10.1/24
|
|
||||||
```
|
|
||||||
```
|
|
||||||
$ ping 10.10.10.2
|
|
||||||
```
|
|
||||||
```
|
|
||||||
$ openlan route add --network ipsec --prefix 192.168.2.0/24 --gateway spi:13
|
|
||||||
```
|
|
@@ -1,74 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/luscis/openlan/pkg/cache"
|
|
||||||
"github.com/luscis/openlan/pkg/models"
|
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Esp struct {
|
|
||||||
Switcher Switcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Esp) Router(router *mux.Router) {
|
|
||||||
router.HandleFunc("/api/esp", l.List).Methods("GET")
|
|
||||||
router.HandleFunc("/api/esp/{id}", l.List).Methods("GET")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Esp) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
data := make([]schema.Esp, 0, 1024)
|
|
||||||
for e := range cache.Esp.List() {
|
|
||||||
if e == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
item := models.NewEspSchema(e)
|
|
||||||
data = append(data, item)
|
|
||||||
}
|
|
||||||
ResponseJson(w, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspState struct {
|
|
||||||
Switcher Switcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l EspState) Router(router *mux.Router) {
|
|
||||||
router.HandleFunc("/api/state", l.List).Methods("GET")
|
|
||||||
router.HandleFunc("/api/state/{id}", l.List).Methods("GET")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l EspState) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
name := vars["id"]
|
|
||||||
data := make([]schema.EspState, 0, 1024)
|
|
||||||
for e := range cache.EspState.List(name) {
|
|
||||||
if e == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data = append(data, models.NewEspStateSchema(e))
|
|
||||||
}
|
|
||||||
ResponseJson(w, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspPolicy struct {
|
|
||||||
Switcher Switcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l EspPolicy) Router(router *mux.Router) {
|
|
||||||
router.HandleFunc("/api/policy", l.List).Methods("GET")
|
|
||||||
router.HandleFunc("/api/policy/{id}", l.List).Methods("GET")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l EspPolicy) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
name := vars["id"]
|
|
||||||
data := make([]schema.EspPolicy, 0, 1024)
|
|
||||||
for e := range cache.EspPolicy.List(name) {
|
|
||||||
if e == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data = append(data, models.NewEspPolicySchema(e))
|
|
||||||
}
|
|
||||||
ResponseJson(w, data)
|
|
||||||
}
|
|
@@ -15,9 +15,6 @@ func Add(router *mux.Router, switcher Switcher) {
|
|||||||
VPNClient{}.Router(router)
|
VPNClient{}.Router(router)
|
||||||
PProf{}.Router(router)
|
PProf{}.Router(router)
|
||||||
VxLAN{}.Router(router)
|
VxLAN{}.Router(router)
|
||||||
Esp{}.Router(router)
|
|
||||||
EspState{}.Router(router)
|
|
||||||
EspPolicy{}.Router(router)
|
|
||||||
Config{Switcher: switcher}.Router(router)
|
Config{Switcher: switcher}.Router(router)
|
||||||
Version{}.Router(router)
|
Version{}.Router(router)
|
||||||
Log{}.Router(router)
|
Log{}.Router(router)
|
||||||
|
141
pkg/cache/ipsec.go
vendored
141
pkg/cache/ipsec.go
vendored
@@ -1,141 +0,0 @@
|
|||||||
package cache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
"github.com/luscis/openlan/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type EspSmap struct {
|
|
||||||
Esp *libol.SafeStrMap
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmap) Init(size int) {
|
|
||||||
p.Esp = libol.NewSafeStrMap(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmap) Add(EspSmap *models.Esp) {
|
|
||||||
_ = p.Esp.Set(EspSmap.ID(), EspSmap)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmap) Get(key string) *models.Esp {
|
|
||||||
ret := p.Esp.Get(key)
|
|
||||||
if ret != nil {
|
|
||||||
return ret.(*models.Esp)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmap) Del(key string) {
|
|
||||||
p.Esp.Del(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmap) List() <-chan *models.Esp {
|
|
||||||
c := make(chan *models.Esp, 128)
|
|
||||||
go func() {
|
|
||||||
p.Esp.Iter(func(k string, v interface{}) {
|
|
||||||
m := v.(*models.Esp)
|
|
||||||
m.Update()
|
|
||||||
c <- m
|
|
||||||
})
|
|
||||||
c <- nil //Finish channel by nil.
|
|
||||||
}()
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
var Esp = EspSmap{
|
|
||||||
Esp: libol.NewSafeStrMap(1024),
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspSmapState struct {
|
|
||||||
State *libol.SafeStrMap
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapState) Init(size int) {
|
|
||||||
p.State = libol.NewSafeStrMap(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapState) Add(EspSmap *models.EspState) {
|
|
||||||
_ = p.State.Set(EspSmap.ID(), EspSmap)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapState) Get(key string) *models.EspState {
|
|
||||||
ret := p.State.Get(key)
|
|
||||||
if ret != nil {
|
|
||||||
return ret.(*models.EspState)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapState) Del(key string) {
|
|
||||||
p.State.Del(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapState) List(name string) <-chan *models.EspState {
|
|
||||||
c := make(chan *models.EspState, 128)
|
|
||||||
go func() {
|
|
||||||
p.State.Iter(func(k string, v interface{}) {
|
|
||||||
m := v.(*models.EspState)
|
|
||||||
if m.Name == name || name == "" {
|
|
||||||
m.Update()
|
|
||||||
c <- m
|
|
||||||
}
|
|
||||||
})
|
|
||||||
c <- nil //Finish channel by nil.
|
|
||||||
}()
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapState) Clear() {
|
|
||||||
p.State.Clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
var EspState = EspSmapState{
|
|
||||||
State: libol.NewSafeStrMap(1024),
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspSmapPolicy struct {
|
|
||||||
Policy *libol.SafeStrMap
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapPolicy) Init(size int) {
|
|
||||||
p.Policy = libol.NewSafeStrMap(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapPolicy) Add(EspSmap *models.EspPolicy) {
|
|
||||||
_ = p.Policy.Set(EspSmap.ID(), EspSmap)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapPolicy) Get(key string) *models.EspPolicy {
|
|
||||||
ret := p.Policy.Get(key)
|
|
||||||
if ret != nil {
|
|
||||||
return ret.(*models.EspPolicy)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapPolicy) Del(key string) {
|
|
||||||
p.Policy.Del(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapPolicy) List(name string) <-chan *models.EspPolicy {
|
|
||||||
c := make(chan *models.EspPolicy, 128)
|
|
||||||
go func() {
|
|
||||||
p.Policy.Iter(func(k string, v interface{}) {
|
|
||||||
m := v.(*models.EspPolicy)
|
|
||||||
if m.Name == name || name == "" {
|
|
||||||
m.Update()
|
|
||||||
c <- m
|
|
||||||
}
|
|
||||||
})
|
|
||||||
c <- nil //Finish channel by nil.
|
|
||||||
}()
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspSmapPolicy) Clear() {
|
|
||||||
p.Policy.Clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
var EspPolicy = EspSmapPolicy{
|
|
||||||
Policy: libol.NewSafeStrMap(1024),
|
|
||||||
}
|
|
5
pkg/cache/store.go
vendored
5
pkg/cache/store.go
vendored
@@ -10,12 +10,7 @@ func Init(cfg *config.Perf) {
|
|||||||
Neighbor.Init(cfg.Neighbor)
|
Neighbor.Init(cfg.Neighbor)
|
||||||
Online.Init(cfg.OnLine)
|
Online.Init(cfg.OnLine)
|
||||||
User.Init(cfg.User)
|
User.Init(cfg.User)
|
||||||
Esp.Init(cfg.Esp)
|
|
||||||
EspState.Init(cfg.State)
|
|
||||||
EspPolicy.Init(cfg.Policy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Reload() {
|
func Reload() {
|
||||||
EspState.Clear()
|
|
||||||
EspPolicy.Clear()
|
|
||||||
}
|
}
|
||||||
|
31
pkg/cache/store_test.go
vendored
31
pkg/cache/store_test.go
vendored
@@ -2,12 +2,12 @@ package cache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/luscis/openlan/pkg/config"
|
"github.com/luscis/openlan/pkg/config"
|
||||||
"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/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SocketClientMock struct {
|
type SocketClientMock struct {
|
||||||
@@ -28,31 +28,4 @@ func TestInit(t *testing.T) {
|
|||||||
Client: &SocketClientMock{},
|
Client: &SocketClientMock{},
|
||||||
})
|
})
|
||||||
assert.Equal(t, 1, Point.Clients.Len(), "MUST be same")
|
assert.Equal(t, 1, Point.Clients.Len(), "MUST be same")
|
||||||
EspState.Add(&models.EspState{
|
|
||||||
EspState: &schema.EspState{},
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, EspState.State.Len(), "MUST be same")
|
|
||||||
User.Add(&models.User{
|
|
||||||
Alias: "fake",
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, User.Users.Len(), "MUST be same")
|
|
||||||
Link.Add("fake-uuid", &models.Link{
|
|
||||||
User: "fake",
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, Link.Links.Len(), "MUST be same")
|
|
||||||
EspPolicy.Add(&models.EspPolicy{
|
|
||||||
EspPolicy: &schema.EspPolicy{},
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, EspPolicy.Policy.Len(), "MUST be same")
|
|
||||||
Online.Add(&models.Line{
|
|
||||||
EthType: 0,
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, Online.Lines.Len(), "MUST be same")
|
|
||||||
Neighbor.Add(&models.Neighbor{
|
|
||||||
Network: "fake",
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, Neighbor.Neighbors.Len(), "MUST be same")
|
|
||||||
Reload()
|
|
||||||
assert.Equal(t, 0, EspState.State.Len(), "MUST be same")
|
|
||||||
assert.Equal(t, 0, EspPolicy.Policy.Len(), "MUST be same")
|
|
||||||
}
|
}
|
||||||
|
@@ -1,266 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
EspAuth = "8bc736635c0642aebc20ba5420c3e93a"
|
|
||||||
EspCrypt = "4ac161f6635843b8b02c60cc36822515"
|
|
||||||
EspLocalUdp = 4500
|
|
||||||
EspRemoteUdp = 4500
|
|
||||||
)
|
|
||||||
|
|
||||||
func Addr2Cidr(addr string) string {
|
|
||||||
if !strings.Contains(addr, "/") {
|
|
||||||
return addr + "/32"
|
|
||||||
}
|
|
||||||
return addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetLocalUdp(port string) {
|
|
||||||
if udp, err := strconv.Atoi(port); err == nil {
|
|
||||||
EspLocalUdp = udp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspState struct {
|
|
||||||
Local string `json:"local,omitempty"`
|
|
||||||
LocalIp net.IP `json:"localAddr,omitempty"`
|
|
||||||
Remote string `json:"remote,omitempty"`
|
|
||||||
RemotePort int `json:"remotePort,omitempty"`
|
|
||||||
RemoteIp net.IP `json:"remoteAddr,omitempty"`
|
|
||||||
Encap string `json:"encapsulation,omitempty"`
|
|
||||||
Auth string `json:"auth,omitempty"`
|
|
||||||
Crypt string `json:"crypt,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EspState) Padding(value string, size int) string {
|
|
||||||
return strings.Repeat(value, 64/len(value))[:size]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EspState) Merge(obj *EspState) {
|
|
||||||
if obj == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if s.Local == "" {
|
|
||||||
s.Local = obj.Local
|
|
||||||
}
|
|
||||||
if s.Auth == "" {
|
|
||||||
s.Auth = obj.Auth
|
|
||||||
}
|
|
||||||
if s.Crypt == "" {
|
|
||||||
s.Crypt = obj.Crypt
|
|
||||||
}
|
|
||||||
if s.RemotePort == 0 {
|
|
||||||
s.RemotePort = obj.RemotePort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *EspState) Correct() {
|
|
||||||
if addr, _ := net.LookupIP(s.Local); len(addr) > 0 {
|
|
||||||
s.LocalIp = addr[0]
|
|
||||||
}
|
|
||||||
if addr, _ := net.LookupIP(s.Remote); len(addr) > 0 {
|
|
||||||
s.RemoteIp = addr[0]
|
|
||||||
}
|
|
||||||
if s.LocalIp == nil && s.RemoteIp != nil {
|
|
||||||
addr, _ := libol.GetLocalByGw(s.RemoteIp.String())
|
|
||||||
s.Local = addr.String()
|
|
||||||
s.LocalIp = addr
|
|
||||||
}
|
|
||||||
if s.Crypt == "" {
|
|
||||||
s.Crypt = s.Auth
|
|
||||||
}
|
|
||||||
if s.Auth == "" {
|
|
||||||
s.Auth = EspAuth
|
|
||||||
}
|
|
||||||
if s.Crypt == "" {
|
|
||||||
s.Crypt = EspCrypt
|
|
||||||
}
|
|
||||||
if s.Encap == "" {
|
|
||||||
s.Encap = "udp"
|
|
||||||
}
|
|
||||||
if s.RemotePort == 0 {
|
|
||||||
s.RemotePort = EspRemoteUdp
|
|
||||||
}
|
|
||||||
s.Auth = s.Padding(s.Auth, 32)
|
|
||||||
s.Crypt = s.Padding(s.Crypt, 32)
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspPolicy struct {
|
|
||||||
Source string `json:"source,omitempty"`
|
|
||||||
Dest string `json:"destination,omitempty"`
|
|
||||||
Priority int `json:"priority,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EspPolicy) Correct() {
|
|
||||||
if p.Source == "" {
|
|
||||||
p.Source = "0.0.0.0/0"
|
|
||||||
}
|
|
||||||
p.Priority = 128 - libol.GetPrefixLen(p.Dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspMember struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
Address string `json:"address,omitempty"`
|
|
||||||
Peer string `json:"peer"`
|
|
||||||
Spi int `json:"spi"`
|
|
||||||
State EspState `json:"state"`
|
|
||||||
Policies []*EspPolicy `json:"policies"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *EspMember) Correct() {
|
|
||||||
if m.Name == "" {
|
|
||||||
m.Name = fmt.Sprintf("spi:%d", m.Spi)
|
|
||||||
} else if m.Spi == 0 {
|
|
||||||
_, _ = fmt.Sscanf(m.Name, "spi:%d", &m.Spi)
|
|
||||||
}
|
|
||||||
if m.Address == "" || m.Peer == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m.Peer = Addr2Cidr(m.Peer)
|
|
||||||
m.Address = Addr2Cidr(m.Address)
|
|
||||||
m.State.Correct()
|
|
||||||
if m.Policies == nil {
|
|
||||||
m.Policies = make([]*EspPolicy, 0, 2)
|
|
||||||
}
|
|
||||||
found := -1
|
|
||||||
for index, pol := range m.Policies {
|
|
||||||
pol.Correct()
|
|
||||||
if pol.Dest != m.Peer {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found = index
|
|
||||||
}
|
|
||||||
if found < 0 {
|
|
||||||
pol := &EspPolicy{
|
|
||||||
Dest: m.Peer,
|
|
||||||
}
|
|
||||||
pol.Correct()
|
|
||||||
m.Policies = append(m.Policies, pol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *EspMember) AddPolicy(obj *EspPolicy) {
|
|
||||||
found := -1
|
|
||||||
for index, po := range m.Policies {
|
|
||||||
if po.Dest != obj.Dest {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found = index
|
|
||||||
po.Source = obj.Source
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if found < 0 {
|
|
||||||
obj.Correct()
|
|
||||||
m.Policies = append(m.Policies, obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *EspMember) RemovePolicy(dest string) bool {
|
|
||||||
found := -1
|
|
||||||
for index, po := range m.Policies {
|
|
||||||
if po.Dest != dest {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found = index
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if found >= 0 {
|
|
||||||
copy(m.Policies[found:], m.Policies[found+1:])
|
|
||||||
m.Policies = m.Policies[:len(m.Policies)-1]
|
|
||||||
}
|
|
||||||
return found >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspSpecifies struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Address string `json:"address,omitempty"`
|
|
||||||
State EspState `json:"state,omitempty"`
|
|
||||||
Members []*EspMember `json:"members"`
|
|
||||||
Listen string `json:"listen,omitempty"`
|
|
||||||
TcpMss int `json:"tcpMss"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *EspSpecifies) Correct() {
|
|
||||||
if n.Listen != "" {
|
|
||||||
addr, port := libol.GetHostPort(n.Listen)
|
|
||||||
if addr != "" {
|
|
||||||
n.State.Local = addr
|
|
||||||
}
|
|
||||||
if port != "" {
|
|
||||||
SetLocalUdp(port)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n.State.Correct()
|
|
||||||
for _, m := range n.Members {
|
|
||||||
if m.Address == "" {
|
|
||||||
m.Address = n.Address
|
|
||||||
}
|
|
||||||
m.State.Merge(&n.State)
|
|
||||||
m.Correct()
|
|
||||||
}
|
|
||||||
if n.TcpMss == 0 {
|
|
||||||
n.TcpMss = 1430 // 1460 - 20 - 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *EspSpecifies) GetMember(name string) *EspMember {
|
|
||||||
for _, mem := range n.Members {
|
|
||||||
if mem.Name == name {
|
|
||||||
return mem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *EspSpecifies) HasRemote(name, addr string) bool {
|
|
||||||
for _, mem := range n.Members {
|
|
||||||
state := mem.State
|
|
||||||
if state.Remote != name || state.RemoteIp.String() == addr {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *EspSpecifies) AddMember(obj *EspMember) {
|
|
||||||
found := -1
|
|
||||||
for index, mem := range n.Members {
|
|
||||||
if mem.Spi != obj.Spi && mem.Name != obj.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found = index
|
|
||||||
if len(obj.Policies) == 0 {
|
|
||||||
obj.Policies = mem.Policies
|
|
||||||
}
|
|
||||||
n.Members[index] = obj
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if found < 0 {
|
|
||||||
n.Members = append(n.Members, obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *EspSpecifies) DelMember(name string) bool {
|
|
||||||
found := -1
|
|
||||||
for index, mem := range n.Members {
|
|
||||||
if mem.Name != name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
found = index
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if found >= 0 {
|
|
||||||
copy(n.Members[found:], n.Members[found+1:])
|
|
||||||
n.Members = n.Members[:len(n.Members)-1]
|
|
||||||
}
|
|
||||||
return found >= 0
|
|
||||||
}
|
|
@@ -1,102 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEspSpecifies(t *testing.T) {
|
|
||||||
spec := EspSpecifies{
|
|
||||||
State: EspState{
|
|
||||||
Local: "3.3.3.1",
|
|
||||||
Crypt: "fake-crypt",
|
|
||||||
Auth: "fake-auth",
|
|
||||||
},
|
|
||||||
Members: []*EspMember{
|
|
||||||
{
|
|
||||||
Peer: "1.1.1.0",
|
|
||||||
Address: "1.1.1.1",
|
|
||||||
Spi: 0x01,
|
|
||||||
State: EspState{
|
|
||||||
Remote: "3.3.3.3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
spec.Correct()
|
|
||||||
assert.Equal(t, spec.State.Local, spec.Members[0].State.Local, "be the same.")
|
|
||||||
assert.Equal(t, spec.State.Crypt, spec.Members[0].State.Crypt, "be the same.")
|
|
||||||
assert.Equal(t, spec.State.Auth, spec.Members[0].State.Auth, "be the same.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEspSpecifies_GetMember(t *testing.T) {
|
|
||||||
spec := EspSpecifies{
|
|
||||||
State: EspState{
|
|
||||||
Local: "3.3.3.1",
|
|
||||||
Crypt: "fake-crypt",
|
|
||||||
Auth: "fake-auth",
|
|
||||||
},
|
|
||||||
Members: []*EspMember{
|
|
||||||
{
|
|
||||||
Peer: "1.1.1.0",
|
|
||||||
Address: "1.1.1.1",
|
|
||||||
Spi: 123,
|
|
||||||
State: EspState{
|
|
||||||
Remote: "3.3.3.3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
spec.Correct()
|
|
||||||
obj := spec.GetMember("spi:123")
|
|
||||||
assert.Equal(t, spec.Members[0], obj, "be the same.")
|
|
||||||
// Add
|
|
||||||
{
|
|
||||||
mem1 := &EspMember{
|
|
||||||
Peer: "1.1.1.0",
|
|
||||||
Address: "1.1.1.2",
|
|
||||||
Spi: 124,
|
|
||||||
State: EspState{
|
|
||||||
Remote: "3.3.3.4",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
spec.AddMember(mem1)
|
|
||||||
spec.Correct()
|
|
||||||
obj1 := spec.GetMember("spi:124")
|
|
||||||
assert.Equal(t, mem1, obj1, "be the same.")
|
|
||||||
}
|
|
||||||
// Delete
|
|
||||||
{
|
|
||||||
spec.DelMember("spi:123")
|
|
||||||
obj0 := spec.GetMember("spi:123")
|
|
||||||
assert.Equal(t, (*EspMember)(nil), obj0, "be the same.")
|
|
||||||
|
|
||||||
spec.DelMember("spi:124")
|
|
||||||
obj1 := spec.GetMember("spi:124")
|
|
||||||
assert.Equal(t, (*EspMember)(nil), obj1, "be the same.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEspSpecifies_AddPolicy(t *testing.T) {
|
|
||||||
mem := &EspMember{
|
|
||||||
Peer: "1.1.1.0",
|
|
||||||
Address: "1.1.1.2",
|
|
||||||
Spi: 124,
|
|
||||||
State: EspState{
|
|
||||||
Local: "3.3.3.1",
|
|
||||||
Remote: "3.3.3.3",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
mem.Correct()
|
|
||||||
assert.Equal(t, 1, len(mem.Policies), "be the same.")
|
|
||||||
{
|
|
||||||
po := &EspPolicy{
|
|
||||||
Dest: "192.1.0.0/24",
|
|
||||||
}
|
|
||||||
mem.AddPolicy(po)
|
|
||||||
assert.Equal(t, 2, len(mem.Policies), "be the same.")
|
|
||||||
mem.RemovePolicy(po.Dest)
|
|
||||||
assert.Equal(t, 1, len(mem.Policies), "be the same.")
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
type L2TP struct {
|
|
||||||
Address string `json:"address"`
|
|
||||||
Subnet *Subnet `json:"subnet,omitempty"`
|
|
||||||
Options []string `json:"Options,omitempty"`
|
|
||||||
IpSec string `json:"ipsec,omitempty"`
|
|
||||||
}
|
|
@@ -31,12 +31,8 @@ type Network struct {
|
|||||||
|
|
||||||
func (n *Network) NewSpecifies() interface{} {
|
func (n *Network) NewSpecifies() interface{} {
|
||||||
switch n.Provider {
|
switch n.Provider {
|
||||||
case "esp":
|
|
||||||
n.Specifies = &EspSpecifies{}
|
|
||||||
case "vxlan":
|
case "vxlan":
|
||||||
n.Specifies = &VxLANSpecifies{}
|
n.Specifies = &VxLANSpecifies{}
|
||||||
case "fabric":
|
|
||||||
n.Specifies = &FabricSpecifies{}
|
|
||||||
case "router":
|
case "router":
|
||||||
n.Specifies = &RouterSpecifies{}
|
n.Specifies = &RouterSpecifies{}
|
||||||
default:
|
default:
|
||||||
@@ -53,25 +49,6 @@ func (n *Network) Correct(sw *Switch) {
|
|||||||
br.Network = n.Name
|
br.Network = n.Name
|
||||||
br.Correct()
|
br.Correct()
|
||||||
switch n.Provider {
|
switch n.Provider {
|
||||||
case "esp":
|
|
||||||
spec := n.Specifies
|
|
||||||
if obj, ok := spec.(*EspSpecifies); ok {
|
|
||||||
obj.Correct()
|
|
||||||
obj.Name = n.Name
|
|
||||||
}
|
|
||||||
case "fabric":
|
|
||||||
// 28 [udp] - 8 [esp] -
|
|
||||||
// 28 [udp] - 8 [vxlan] -
|
|
||||||
// 14 [ethernet] - tcp [40] - 1332 [mss] -
|
|
||||||
// 42 [padding] ~= variable 30-45
|
|
||||||
if br.Mss == 0 {
|
|
||||||
br.Mss = 1332
|
|
||||||
}
|
|
||||||
spec := n.Specifies
|
|
||||||
if obj, ok := spec.(*FabricSpecifies); ok {
|
|
||||||
obj.Correct()
|
|
||||||
obj.Name = n.Name
|
|
||||||
}
|
|
||||||
case "router":
|
case "router":
|
||||||
spec := n.Specifies
|
spec := n.Specifies
|
||||||
if obj, ok := spec.(*RouterSpecifies); ok {
|
if obj, ok := spec.(*RouterSpecifies); ok {
|
||||||
@@ -201,11 +178,4 @@ func (n *Network) SaveNextGroup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *Network) Reload() {
|
func (n *Network) Reload() {
|
||||||
switch n.Provider {
|
|
||||||
case "esp":
|
|
||||||
spec := n.Specifies
|
|
||||||
if obj, ok := spec.(*EspSpecifies); ok {
|
|
||||||
obj.Correct()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -70,7 +70,6 @@ type Switch struct {
|
|||||||
AddrPool string `json:"pool,omitempty"`
|
AddrPool string `json:"pool,omitempty"`
|
||||||
ConfDir string `json:"-"`
|
ConfDir string `json:"-"`
|
||||||
TokenFile string `json:"-"`
|
TokenFile string `json:"-"`
|
||||||
L2TP *L2TP `json:"l2tp"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSwitch() *Switch {
|
func NewSwitch() *Switch {
|
||||||
|
@@ -1,195 +0,0 @@
|
|||||||
package libol
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/ip.h>
|
|
||||||
#include <linux/udp.h>
|
|
||||||
#include <linux/xfrm.h>
|
|
||||||
#include <linux/ipsec.h>
|
|
||||||
#include <linux/pfkeyv2.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_int32_t padding[2];
|
|
||||||
u_int32_t spi;
|
|
||||||
u_int32_t seqno;
|
|
||||||
char hostname[32];
|
|
||||||
} udpin_message;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_int16_t port;
|
|
||||||
int32_t socket;
|
|
||||||
} udpin_server;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t socket;
|
|
||||||
uint16_t remote_port;
|
|
||||||
const char *remote_addr;
|
|
||||||
u_int32_t spi;
|
|
||||||
u_int32_t seqno;
|
|
||||||
char hostname[32];
|
|
||||||
} udpin_connection;
|
|
||||||
|
|
||||||
int seqno = 0;
|
|
||||||
|
|
||||||
int send_ping_once(udpin_connection *conn) {
|
|
||||||
int retval = 0;
|
|
||||||
struct sockaddr_in dstaddr = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = htons(conn->remote_port),
|
|
||||||
.sin_addr = {
|
|
||||||
.s_addr = inet_addr(conn->remote_addr),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
udpin_message data = {
|
|
||||||
.padding = {0, 0},
|
|
||||||
.spi = htonl(conn->spi),
|
|
||||||
.hostname = {0},
|
|
||||||
};
|
|
||||||
data.seqno = htonl(conn->seqno);
|
|
||||||
gethostname(data.hostname, sizeof data.hostname - 1);
|
|
||||||
|
|
||||||
retval = sendto(conn->socket, &data, sizeof data, 0, (struct sockaddr *)&dstaddr, sizeof dstaddr);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int recv_ping_once(udpin_server *srv, udpin_connection *from) {
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int addrlen = sizeof addr;
|
|
||||||
udpin_message data;
|
|
||||||
int datalen = sizeof data;
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
memset(&data, 0, sizeof data);
|
|
||||||
retval = recvfrom(srv->socket, &data, datalen, 0, (struct sockaddr *)&addr, &addrlen);
|
|
||||||
if ( retval <= 0 ) {
|
|
||||||
if (errno == EAGAIN) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
from->spi = ntohl(data.spi);
|
|
||||||
from->remote_addr = inet_ntoa(addr.sin_addr);
|
|
||||||
from->remote_port = ntohs(addr.sin_port);
|
|
||||||
strncpy(from->hostname, data.hostname, sizeof from->hostname);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int open_socket(udpin_server *srv) {
|
|
||||||
int op = 1;
|
|
||||||
struct sockaddr_in addr = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = htons(srv->port),
|
|
||||||
.sin_addr = {
|
|
||||||
.s_addr = INADDR_ANY,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
srv->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
if (srv->socket == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = setsockopt(srv->socket, SOL_SOCKET, SO_REUSEADDR, &op, sizeof op);
|
|
||||||
if (retval < 0) {
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
retval = bind(srv->socket, (struct sockaddr *)&addr, sizeof addr);
|
|
||||||
if ( retval == -1) {
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int configure_socket(udpin_server *srv) {
|
|
||||||
int encap = UDP_ENCAP_ESPINUDP;
|
|
||||||
|
|
||||||
return setsockopt(srv->socket, IPPROTO_UDP, UDP_ENCAP, &encap, sizeof encap);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UdpInServer struct {
|
|
||||||
Port uint16
|
|
||||||
Socket int
|
|
||||||
server *C.udpin_server
|
|
||||||
SeqNo uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type UdpInConnection struct {
|
|
||||||
Socket int
|
|
||||||
RemotePort uint16
|
|
||||||
RemoteAddr string
|
|
||||||
Spi uint32
|
|
||||||
Hostname string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UdpInConnection) Connection() string {
|
|
||||||
return fmt.Sprintf("%s:%d", c.RemoteAddr, c.RemotePort)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *UdpInConnection) String() string {
|
|
||||||
return fmt.Sprintf("%d on %s:%d", c.Spi, c.RemoteAddr, c.RemotePort)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpInServer) Open() error {
|
|
||||||
server := &C.udpin_server{
|
|
||||||
port: C.ushort(u.Port),
|
|
||||||
socket: -1,
|
|
||||||
}
|
|
||||||
if ret := C.open_socket(server); ret < 0 {
|
|
||||||
return NewErr("UdpInServer.Open errno:%d", ret)
|
|
||||||
}
|
|
||||||
if ret := C.configure_socket(server); ret < 0 {
|
|
||||||
return NewErr("UdpInServer.Open errno:%d", ret)
|
|
||||||
}
|
|
||||||
u.server = server
|
|
||||||
u.Socket = int(server.socket)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpInServer) Send(to *UdpInConnection) error {
|
|
||||||
u.SeqNo += 1
|
|
||||||
addr := C.CString(LookupIP(to.RemoteAddr))
|
|
||||||
defer C.free(unsafe.Pointer(addr))
|
|
||||||
conn := &C.udpin_connection{
|
|
||||||
socket: u.server.socket,
|
|
||||||
spi: C.uint(to.Spi),
|
|
||||||
remote_port: C.ushort(to.RemotePort),
|
|
||||||
remote_addr: addr,
|
|
||||||
seqno: C.uint(u.SeqNo),
|
|
||||||
}
|
|
||||||
if ret := C.send_ping_once(conn); ret < 0 {
|
|
||||||
return NewErr("UdpInServer.Ping errno:%d", ret)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UdpInServer) Recv() (*UdpInConnection, error) {
|
|
||||||
from := &C.udpin_connection{}
|
|
||||||
if ret := C.recv_ping_once(u.server, from); ret < 0 {
|
|
||||||
return nil, NewErr("UdpInServer.Pong errno:%d", ret)
|
|
||||||
}
|
|
||||||
return &UdpInConnection{
|
|
||||||
RemotePort: uint16(from.remote_port),
|
|
||||||
RemoteAddr: C.GoString(from.remote_addr),
|
|
||||||
Spi: uint32(from.spi),
|
|
||||||
Hostname: C.GoString(&from.hostname[0]),
|
|
||||||
}, nil
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
package libol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOpenUDP_C(t *testing.T) {
|
|
||||||
udp := &UdpInServer{Port: 4500}
|
|
||||||
err := udp.Open()
|
|
||||||
assert.Equal(t, nil, err, "has not error")
|
|
||||||
assert.NotEqual(t, -1, udp.Socket, "valid socket")
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
conn, err := udp.Recv()
|
|
||||||
fmt.Println(conn, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
err = udp.Send(&UdpInConnection{
|
|
||||||
Spi: 84209,
|
|
||||||
RemoteAddr: "180.109.49.146",
|
|
||||||
RemotePort: 4500,
|
|
||||||
})
|
|
||||||
assert.Equal(t, nil, err, "has not error")
|
|
||||||
time.Sleep(time.Second * 2)
|
|
||||||
}
|
|
@@ -1,94 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
|
||||||
nl "github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Esp struct {
|
|
||||||
Name string
|
|
||||||
Address string
|
|
||||||
NewTime int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Esp) Update() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Esp) ID() string {
|
|
||||||
return l.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEspSchema(e *Esp) schema.Esp {
|
|
||||||
e.Update()
|
|
||||||
se := schema.Esp{
|
|
||||||
Name: e.Name,
|
|
||||||
Address: e.Address,
|
|
||||||
}
|
|
||||||
return se
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspState struct {
|
|
||||||
*schema.EspState
|
|
||||||
NewTime int64
|
|
||||||
In *nl.XfrmState
|
|
||||||
Out *nl.XfrmState
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *EspState) ID() string {
|
|
||||||
return fmt.Sprintf("spi:%d %s-%s", l.Spi, l.Local, l.Remote)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *EspState) UpTime() int64 {
|
|
||||||
return time.Now().Unix() - l.NewTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *EspState) String() string {
|
|
||||||
return fmt.Sprintf("{Spi: %d Local: %s Remote: %s}", l.Spi, l.Local, l.Remote)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEspStateSchema(e *EspState) schema.EspState {
|
|
||||||
e.Update()
|
|
||||||
se := schema.EspState{
|
|
||||||
Name: e.Name,
|
|
||||||
Spi: e.Spi,
|
|
||||||
Local: e.Local,
|
|
||||||
Remote: e.Remote,
|
|
||||||
TxBytes: e.TxBytes,
|
|
||||||
TxPackages: e.TxPackages,
|
|
||||||
RxBytes: e.RxBytes,
|
|
||||||
RxPackages: e.RxPackages,
|
|
||||||
AliveTime: e.AliveTime,
|
|
||||||
}
|
|
||||||
return se
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspPolicy struct {
|
|
||||||
*schema.EspPolicy
|
|
||||||
In *nl.XfrmPolicy
|
|
||||||
Fwd *nl.XfrmPolicy
|
|
||||||
Out *nl.XfrmPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *EspPolicy) ID() string {
|
|
||||||
return fmt.Sprintf("spi:%d %s-%s", l.Spi, l.Source, l.Dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *EspPolicy) String() string {
|
|
||||||
return fmt.Sprintf("{Spi: %d Source: %s Dest: %s}", l.Spi, l.Source, l.Dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *EspPolicy) Update() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEspPolicySchema(e *EspPolicy) schema.EspPolicy {
|
|
||||||
e.Update()
|
|
||||||
se := schema.EspPolicy{
|
|
||||||
Name: e.Name,
|
|
||||||
Source: e.Source,
|
|
||||||
Dest: e.Dest,
|
|
||||||
}
|
|
||||||
return se
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
nl "github.com/vishvananda/netlink"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (l *EspState) Update() {
|
|
||||||
used := int64(0)
|
|
||||||
if xss, err := nl.XfrmStateGet(l.In); xss != nil {
|
|
||||||
l.TxBytes = xss.Statistics.Bytes
|
|
||||||
l.TxPackages = xss.Statistics.Packets
|
|
||||||
used = int64(xss.Statistics.UseTime)
|
|
||||||
} else {
|
|
||||||
libol.Debug("EspState.Update %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if xss, err := nl.XfrmStateGet(l.Out); xss != nil {
|
|
||||||
l.RxBytes = xss.Statistics.Bytes
|
|
||||||
l.RxPackages = xss.Statistics.Packets
|
|
||||||
} else {
|
|
||||||
libol.Debug("EspState.Update %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if used > 0 {
|
|
||||||
l.AliveTime = time.Now().Unix() - used
|
|
||||||
}
|
|
||||||
}
|
|
@@ -132,7 +132,7 @@
|
|||||||
<div class="link">
|
<div class="link">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<div>
|
<div>
|
||||||
<span>The link which connect to other, and total </span><span>{{ len .States }}+{{ len .Links }}</span>.
|
<span>The link which connect to other, and total </span><span>{{ len .Links }}</span>.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
@@ -166,22 +166,6 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ range .States }}
|
|
||||||
<tr>
|
|
||||||
<td>{{ .Name }}</td>
|
|
||||||
<td>{{ prettyTime .AliveTime }}</td>
|
|
||||||
<td>loopback</td>
|
|
||||||
<td>ID:{{ .Spi }}</td>
|
|
||||||
<td>esp</td>
|
|
||||||
<td><a href="https://{{ .Remote }}:10000">{{ .Remote }}</a></td>
|
|
||||||
<td>{{ .RxBytes }} | {{ .TxBytes }}</td>
|
|
||||||
<td>
|
|
||||||
{{ if .RxBytes }}<span class="success">success</span>
|
|
||||||
{{ else }}<span class="unknown">unknown</span>
|
|
||||||
{{ end}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
{{ range .Links }}
|
{{ range .Links }}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ .UUID }}</td>
|
<td>{{ .UUID }}</td>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
@@ -1,410 +0,0 @@
|
|||||||
package cswitch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/luscis/openlan/pkg/api"
|
|
||||||
"github.com/luscis/openlan/pkg/config"
|
|
||||||
"github.com/luscis/openlan/pkg/database"
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
"github.com/ovn-org/libovsdb/cache"
|
|
||||||
"github.com/ovn-org/libovsdb/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ConfD struct {
|
|
||||||
stop chan struct{}
|
|
||||||
out *libol.SubLogger
|
|
||||||
api api.Switcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfd(api api.Switcher) *ConfD {
|
|
||||||
c := &ConfD{
|
|
||||||
out: libol.NewSubLogger("confd"),
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
api: api,
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) Initialize() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) Start() {
|
|
||||||
c.out.Info("ConfD.Start")
|
|
||||||
handler := &cache.EventHandlerFuncs{
|
|
||||||
AddFunc: c.Add,
|
|
||||||
DeleteFunc: c.Delete,
|
|
||||||
UpdateFunc: c.Update,
|
|
||||||
}
|
|
||||||
if _, err := database.NewConfClient(handler); err != nil {
|
|
||||||
c.out.Error("ConfD.Start open db with %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) Stop() {
|
|
||||||
c.out.Info("ConfD.Stop")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) Add(table string, model model.Model) {
|
|
||||||
c.out.Cmd("ConfD.Add %s %v", table, model)
|
|
||||||
if obj, ok := model.(*database.Switch); ok {
|
|
||||||
c.out.Info("ConfD.Add switch %d", obj.Listen)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := model.(*database.VirtualNetwork); ok {
|
|
||||||
c.out.Info("ConfD.Add virtual network %s:%s", obj.Name, obj.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := model.(*database.VirtualLink); ok {
|
|
||||||
c.out.Info("ConfD.Add virtual link %s:%s", obj.Network, obj.Connection)
|
|
||||||
c.AddLink(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := model.(*database.NameCache); ok {
|
|
||||||
c.out.Info("ConfD.Add name cache %s", obj.Name)
|
|
||||||
c.UpdateName(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := model.(*database.PrefixRoute); ok {
|
|
||||||
c.out.Info("ConfD.Add prefix route %s:%s", obj.Network, obj.Prefix)
|
|
||||||
c.AddRoute(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) Delete(table string, model model.Model) {
|
|
||||||
c.out.Cmd("ConfD.Delete %s %v", table, model)
|
|
||||||
if obj, ok := model.(*database.VirtualNetwork); ok {
|
|
||||||
c.out.Info("ConfD.Delete virtual network %s:%s", obj.Name, obj.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := model.(*database.VirtualLink); ok {
|
|
||||||
c.out.Info("ConfD.Delete virtual link %s:%s", obj.Network, obj.Connection)
|
|
||||||
c.DelLink(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := model.(*database.PrefixRoute); ok {
|
|
||||||
c.out.Info("ConfD.Delete prefix route %s:%s", obj.Network, obj.Prefix)
|
|
||||||
c.DelRoute(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) Update(table string, old model.Model, new model.Model) {
|
|
||||||
c.out.Cmd("ConfD.Update %s %v", table, new)
|
|
||||||
if obj, ok := new.(*database.VirtualNetwork); ok {
|
|
||||||
c.out.Info("ConfD.Update virtual network %s:%s", obj.Name, obj.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ob1, ok := new.(*database.VirtualLink); ok {
|
|
||||||
ob0, _ := old.(*database.VirtualLink)
|
|
||||||
oldConn := ob0.Status["remote_connection"]
|
|
||||||
newConn := ob1.Status["remote_connection"]
|
|
||||||
c.out.Info("ConfD.Update virtual link %s:%s->%s", ob1.Network, oldConn, newConn)
|
|
||||||
if c.DiffLink(ob0, ob1) {
|
|
||||||
c.AddLink(ob1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj, ok := new.(*database.NameCache); ok {
|
|
||||||
c.out.Info("ConfD.Update name cache %s", obj.Name)
|
|
||||||
c.UpdateName(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRoutes(result *[]database.PrefixRoute, device string) error {
|
|
||||||
if err := database.Client.WhereList(
|
|
||||||
func(l *database.PrefixRoute) bool {
|
|
||||||
return l.Gateway == device
|
|
||||||
}, result); err != nil {
|
|
||||||
libol.Warn("GetRoutes %v has %s", device, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) DiffLink(old *database.VirtualLink, new *database.VirtualLink) bool {
|
|
||||||
c.out.Cmd("ConfD.Update virtual link %v->%v", old, new)
|
|
||||||
if old.Connection != new.Connection {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if old.Device != new.Device {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if old.Status["remote_connection"] != new.Status["remote_connection"] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if old.OtherConfig["local_address"] != new.OtherConfig["local_address"] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if old.OtherConfig["remote_address"] != new.OtherConfig["remote_address"] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if old.Authentication["username"] != new.Authentication["username"] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if old.Authentication["password"] != new.Authentication["password"] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) AddLink(obj *database.VirtualLink) {
|
|
||||||
worker := api.GetWorker(obj.Network)
|
|
||||||
if worker == nil {
|
|
||||||
c.out.Warn("ConfD.AddLink network %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg := worker.Config()
|
|
||||||
if cfg == nil || cfg.Specifies == nil {
|
|
||||||
c.out.Warn("ConfD.AddLink config %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cfg.Provider == "esp" {
|
|
||||||
link := &MemberLink{
|
|
||||||
LinkImpl{
|
|
||||||
api: c.api,
|
|
||||||
out: c.out,
|
|
||||||
worker: worker,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
link.Add(obj)
|
|
||||||
} else if cfg.Provider == "fabric" {
|
|
||||||
link := &TunnelLink{
|
|
||||||
LinkImpl{
|
|
||||||
api: c.api,
|
|
||||||
out: c.out,
|
|
||||||
worker: worker,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
link.Add(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) DelLink(obj *database.VirtualLink) {
|
|
||||||
worker := api.GetWorker(obj.Network)
|
|
||||||
if worker == nil {
|
|
||||||
c.out.Warn("ConfD.DelLink network %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg := worker.Config()
|
|
||||||
if cfg == nil || cfg.Specifies == nil {
|
|
||||||
c.out.Warn("ConfD.DelLink config %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cfg.Provider == "esp" {
|
|
||||||
link := &MemberLink{
|
|
||||||
LinkImpl{
|
|
||||||
api: c.api,
|
|
||||||
out: c.out,
|
|
||||||
worker: worker,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
link.Del(obj)
|
|
||||||
} else if cfg.Provider == "fabric" {
|
|
||||||
link := &TunnelLink{
|
|
||||||
LinkImpl{
|
|
||||||
api: c.api,
|
|
||||||
out: c.out,
|
|
||||||
worker: worker,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
link.Del(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) UpdateName(obj *database.NameCache) {
|
|
||||||
if obj.Address == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.out.Info("ConfD.UpdateName %s %s", obj.Name, obj.Address)
|
|
||||||
api.ListWorker(func(w api.Networker) {
|
|
||||||
cfg := w.Config()
|
|
||||||
spec := cfg.Specifies
|
|
||||||
if spec == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if specObj, ok := spec.(*config.EspSpecifies); ok {
|
|
||||||
if specObj.HasRemote(obj.Name, obj.Address) {
|
|
||||||
cs := config.Get()
|
|
||||||
cfg.Correct(cs)
|
|
||||||
w.Reload(c.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) AddRoute(obj *database.PrefixRoute) {
|
|
||||||
if obj.Prefix == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
|
||||||
worker := api.GetWorker(obj.Network)
|
|
||||||
if worker == nil {
|
|
||||||
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
netCfg := worker.Config()
|
|
||||||
if netCfg == nil || netCfg.Specifies == nil {
|
|
||||||
c.out.Warn("ConfD.DelRoute config %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
spec := netCfg.Specifies
|
|
||||||
poCfg := &config.EspPolicy{
|
|
||||||
Source: obj.Source,
|
|
||||||
Dest: obj.Prefix,
|
|
||||||
}
|
|
||||||
if specObj, ok := spec.(*config.EspSpecifies); ok {
|
|
||||||
var mem *config.EspMember
|
|
||||||
if mem = specObj.GetMember(obj.Gateway); mem != nil {
|
|
||||||
mem.AddPolicy(poCfg)
|
|
||||||
} else if libol.GetPrefix(obj.Gateway, 4) == "spi:" {
|
|
||||||
mem = &config.EspMember{
|
|
||||||
Name: obj.Gateway,
|
|
||||||
}
|
|
||||||
specObj.AddMember(mem)
|
|
||||||
}
|
|
||||||
if mem != nil {
|
|
||||||
mem.AddPolicy(poCfg)
|
|
||||||
specObj.Correct()
|
|
||||||
worker.Reload(c.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ConfD) DelRoute(obj *database.PrefixRoute) {
|
|
||||||
if obj.Prefix == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.out.Cmd("ConfD.DelRoute %v", obj.Network)
|
|
||||||
worker := api.GetWorker(obj.Network)
|
|
||||||
if worker == nil {
|
|
||||||
c.out.Warn("ConfD.DelRoute network %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
netCfg := worker.Config()
|
|
||||||
if netCfg == nil || netCfg.Specifies == nil {
|
|
||||||
c.out.Warn("ConfD.DelRoute config %s not found.", obj.Network)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
spec := netCfg.Specifies
|
|
||||||
if specObj, ok := spec.(*config.EspSpecifies); ok {
|
|
||||||
if mem := specObj.GetMember(obj.Gateway); mem != nil {
|
|
||||||
if mem.RemovePolicy(obj.Prefix) {
|
|
||||||
specObj.Correct()
|
|
||||||
worker.Reload(c.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type LinkImpl struct {
|
|
||||||
api api.Switcher
|
|
||||||
out *libol.SubLogger
|
|
||||||
worker api.Networker
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LinkImpl) Add(obj *database.VirtualLink) {
|
|
||||||
l.out.Info("LinkImpl.Add TODO")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LinkImpl) Update(obj *database.VirtualLink) {
|
|
||||||
l.out.Info("LinkImpl.Update TODO")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LinkImpl) Del(obj *database.VirtualLink) {
|
|
||||||
l.out.Info("LinkImpl.Del TODO")
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemberLink struct {
|
|
||||||
LinkImpl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *MemberLink) Add(obj *database.VirtualLink) {
|
|
||||||
var port int
|
|
||||||
var remote string
|
|
||||||
|
|
||||||
conn := obj.Connection
|
|
||||||
if conn == "any" {
|
|
||||||
remoteConn := obj.Status["remote_connection"]
|
|
||||||
if libol.GetPrefix(remoteConn, 4) == "udp:" {
|
|
||||||
remote, port = database.GetAddrPort(remoteConn[4:])
|
|
||||||
} else {
|
|
||||||
l.out.Warn("MemberLink.Add %s remote not found.", conn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if libol.GetPrefix(conn, 4) == "udp:" {
|
|
||||||
remoteConn := obj.Connection
|
|
||||||
remote, port = database.GetAddrPort(remoteConn[4:])
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
l.out.Info("MemberLink.Add remote link %s:%d", remote, port)
|
|
||||||
memCfg := &config.EspMember{
|
|
||||||
Name: obj.Device,
|
|
||||||
Address: obj.OtherConfig["local_address"],
|
|
||||||
Peer: obj.OtherConfig["remote_address"],
|
|
||||||
State: config.EspState{
|
|
||||||
Remote: remote,
|
|
||||||
RemotePort: port,
|
|
||||||
Auth: obj.Authentication["password"],
|
|
||||||
Crypt: obj.Authentication["username"],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
var routes []database.PrefixRoute
|
|
||||||
_ = GetRoutes(&routes, obj.Device)
|
|
||||||
for _, route := range routes {
|
|
||||||
l.out.Info("MemberLink.Add %s via %s", route.Prefix, obj.Device)
|
|
||||||
memCfg.AddPolicy(&config.EspPolicy{
|
|
||||||
Source: route.Source,
|
|
||||||
Dest: route.Prefix,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
l.out.Cmd("MemberLink.Add %v", memCfg)
|
|
||||||
spec := l.worker.Config().Specifies
|
|
||||||
if specObj, ok := spec.(*config.EspSpecifies); ok {
|
|
||||||
specObj.AddMember(memCfg)
|
|
||||||
specObj.Correct()
|
|
||||||
l.worker.Reload(l.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *MemberLink) Update(obj *database.VirtualLink) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *MemberLink) Del(obj *database.VirtualLink) {
|
|
||||||
l.out.Info("MemberLink.Del remote link %s", obj.Device)
|
|
||||||
spec := l.worker.Config().Specifies
|
|
||||||
if specObj, ok := spec.(*config.EspSpecifies); ok {
|
|
||||||
if specObj.DelMember(obj.Device) {
|
|
||||||
specObj.Correct()
|
|
||||||
l.worker.Reload(l.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TunnelLink struct {
|
|
||||||
LinkImpl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *TunnelLink) Add(obj *database.VirtualLink) {
|
|
||||||
tunCfg := &config.FabricTunnel{
|
|
||||||
Remote: obj.Connection,
|
|
||||||
}
|
|
||||||
l.out.Cmd("TunnelLink.Add %v", tunCfg)
|
|
||||||
spec := l.worker.Config().Specifies
|
|
||||||
if specObj, ok := spec.(*config.FabricSpecifies); ok {
|
|
||||||
specObj.AddTunnel(tunCfg)
|
|
||||||
specObj.Correct()
|
|
||||||
l.worker.Reload(l.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *TunnelLink) Del(obj *database.VirtualLink) {
|
|
||||||
l.out.Info("TunnelLink.Del remote link %s", obj.Connection)
|
|
||||||
spec := l.worker.Config().Specifies
|
|
||||||
if specObj, ok := spec.(*config.FabricSpecifies); ok {
|
|
||||||
if specObj.DelTunnel(obj.Connection) {
|
|
||||||
specObj.Correct()
|
|
||||||
l.worker.Reload(l.api)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -302,18 +302,6 @@ func (h *Http) getIndex(body *schema.Index) *schema.Index {
|
|||||||
return body.Clients[i].Name < body.Clients[j].Name
|
return body.Clients[i].Name < body.Clients[j].Name
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// display esp state
|
|
||||||
for s := range cache.EspState.List("") {
|
|
||||||
if s == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
body.States = append(body.States, models.NewEspStateSchema(s))
|
|
||||||
}
|
|
||||||
sort.SliceStable(body.States, func(i, j int) bool {
|
|
||||||
ii := body.States[i]
|
|
||||||
jj := body.States[j]
|
|
||||||
return ii.Spi > jj.Spi
|
|
||||||
})
|
|
||||||
|
|
||||||
// display esp state
|
// display esp state
|
||||||
for s := range cache.Output.List("") {
|
for s := range cache.Output.List("") {
|
||||||
|
@@ -1,389 +0,0 @@
|
|||||||
package cswitch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/luscis/openlan/pkg/api"
|
|
||||||
"github.com/luscis/openlan/pkg/cache"
|
|
||||||
co "github.com/luscis/openlan/pkg/config"
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
"github.com/luscis/openlan/pkg/models"
|
|
||||||
"github.com/luscis/openlan/pkg/schema"
|
|
||||||
nl "github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetStateEncap(mode string, sport, dport int) *nl.XfrmStateEncap {
|
|
||||||
if mode == "udp" {
|
|
||||||
return &nl.XfrmStateEncap{
|
|
||||||
Type: nl.XFRM_ENCAP_ESPINUDP,
|
|
||||||
SrcPort: sport,
|
|
||||||
DstPort: dport,
|
|
||||||
OriginalAddress: net.ParseIP("0.0.0.0"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type EspWorker struct {
|
|
||||||
*WorkerImpl
|
|
||||||
proto nl.Proto
|
|
||||||
mode nl.Mode
|
|
||||||
states []*models.EspState
|
|
||||||
policies []*models.EspPolicy
|
|
||||||
spec *co.EspSpecifies
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewESPWorker(c *co.Network) *EspWorker {
|
|
||||||
w := &EspWorker{
|
|
||||||
WorkerImpl: NewWorkerApi(c),
|
|
||||||
proto: nl.XFRM_PROTO_ESP,
|
|
||||||
mode: nl.XFRM_MODE_TUNNEL,
|
|
||||||
}
|
|
||||||
w.spec, _ = c.Specifies.(*co.EspSpecifies)
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
type StateParameters struct {
|
|
||||||
spi int
|
|
||||||
local, remote net.IP
|
|
||||||
auth, crypt string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) newState(args StateParameters) *nl.XfrmState {
|
|
||||||
state := &nl.XfrmState{
|
|
||||||
Src: args.local,
|
|
||||||
Dst: args.remote,
|
|
||||||
Proto: w.proto,
|
|
||||||
Mode: w.mode,
|
|
||||||
Spi: args.spi,
|
|
||||||
Auth: &nl.XfrmStateAlgo{
|
|
||||||
Name: "hmac(sha256)",
|
|
||||||
Key: []byte(args.auth),
|
|
||||||
},
|
|
||||||
Crypt: &nl.XfrmStateAlgo{
|
|
||||||
Name: "cbc(aes)",
|
|
||||||
Key: []byte(args.crypt),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return state
|
|
||||||
}
|
|
||||||
|
|
||||||
type PolicyParameter struct {
|
|
||||||
spi int
|
|
||||||
local, remote net.IP
|
|
||||||
src, dst *net.IPNet
|
|
||||||
dir nl.Dir
|
|
||||||
pri int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) newPolicy(args PolicyParameter) *nl.XfrmPolicy {
|
|
||||||
policy := &nl.XfrmPolicy{
|
|
||||||
Src: args.src,
|
|
||||||
Dst: args.dst,
|
|
||||||
Dir: args.dir,
|
|
||||||
Priority: args.pri,
|
|
||||||
}
|
|
||||||
tmpl := nl.XfrmPolicyTmpl{
|
|
||||||
Src: args.local,
|
|
||||||
Dst: args.remote,
|
|
||||||
Proto: w.proto,
|
|
||||||
Mode: w.mode,
|
|
||||||
Spi: args.spi,
|
|
||||||
}
|
|
||||||
policy.Tmpls = append(policy.Tmpls, tmpl)
|
|
||||||
return policy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) addState(ms *models.EspState) {
|
|
||||||
spi := ms.Spi
|
|
||||||
w.out.Info("EspWorker.addState %s", ms.String())
|
|
||||||
if st := w.newState(StateParameters{
|
|
||||||
spi, ms.Local, ms.Remote, ms.Auth, ms.Crypt,
|
|
||||||
}); st != nil {
|
|
||||||
st.Encap = GetStateEncap(ms.Encap, co.EspLocalUdp, ms.RemotePort)
|
|
||||||
ms.In = st
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if st := w.newState(StateParameters{
|
|
||||||
spi, ms.Remote, ms.Local, ms.Auth, ms.Crypt,
|
|
||||||
}); st != nil {
|
|
||||||
st.Encap = GetStateEncap(ms.Encap, ms.RemotePort, co.EspLocalUdp)
|
|
||||||
ms.Out = st
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.states = append(w.states, ms)
|
|
||||||
cache.EspState.Add(ms)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) delState(ms *models.EspState) {
|
|
||||||
w.out.Info("EspWorker.delState %s", ms.String())
|
|
||||||
cache.EspState.Del(ms.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) addPolicy(mp *models.EspPolicy) {
|
|
||||||
spi := mp.Spi
|
|
||||||
src, err := libol.ParseNet(mp.Source)
|
|
||||||
if err != nil {
|
|
||||||
w.out.Error("EspWorker.addPolicy %s: %s", mp.String(), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dst, err := libol.ParseNet(mp.Dest)
|
|
||||||
if err != nil {
|
|
||||||
w.out.Error("EspWorker.addPolicy %s: %s", mp.String(), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.out.Info("EspWorker.addPolicy %s", mp.String())
|
|
||||||
if po := w.newPolicy(PolicyParameter{
|
|
||||||
spi, mp.Local, mp.Remote, src, dst, nl.XFRM_DIR_OUT, mp.Priority,
|
|
||||||
}); po != nil {
|
|
||||||
mp.Out = po
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if po := w.newPolicy(PolicyParameter{
|
|
||||||
spi, mp.Remote, mp.Local, dst, src, nl.XFRM_DIR_FWD, mp.Priority,
|
|
||||||
}); po != nil {
|
|
||||||
mp.Fwd = po
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if po := w.newPolicy(PolicyParameter{
|
|
||||||
spi, mp.Remote, mp.Local, dst, src, nl.XFRM_DIR_IN, mp.Priority,
|
|
||||||
}); po != nil {
|
|
||||||
mp.In = po
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.policies = append(w.policies, mp)
|
|
||||||
cache.EspPolicy.Add(mp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) delPolicy(mp *models.EspPolicy) {
|
|
||||||
w.out.Info("EspWorker.delPolicy %s", mp.String())
|
|
||||||
cache.EspPolicy.Del(mp.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) updateXfrm() {
|
|
||||||
for _, mem := range w.spec.Members {
|
|
||||||
if mem == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
state := mem.State
|
|
||||||
if state.LocalIp == nil || state.RemoteIp == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ms := &models.EspState{
|
|
||||||
EspState: &schema.EspState{
|
|
||||||
Name: w.spec.Name,
|
|
||||||
Spi: mem.Spi,
|
|
||||||
Local: state.LocalIp,
|
|
||||||
Remote: state.RemoteIp,
|
|
||||||
Proto: uint8(w.proto),
|
|
||||||
Mode: uint8(w.mode),
|
|
||||||
Encap: state.Encap,
|
|
||||||
Auth: state.Auth,
|
|
||||||
Crypt: state.Crypt,
|
|
||||||
RemotePort: state.RemotePort,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
w.addState(ms)
|
|
||||||
for _, pol := range mem.Policies {
|
|
||||||
if pol == nil || pol.Dest == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mp := &models.EspPolicy{
|
|
||||||
EspPolicy: &schema.EspPolicy{
|
|
||||||
Name: w.spec.Name,
|
|
||||||
Spi: mem.Spi,
|
|
||||||
Local: state.LocalIp,
|
|
||||||
Remote: state.RemoteIp,
|
|
||||||
Source: pol.Source,
|
|
||||||
Dest: pol.Dest,
|
|
||||||
Priority: pol.Priority,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
w.addPolicy(mp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) Initialize() {
|
|
||||||
w.WorkerImpl.Initialize()
|
|
||||||
w.updateXfrm()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) addRoute(device, src, remote string) error {
|
|
||||||
link, err := nl.LinkByName(device)
|
|
||||||
if link == nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// add peer routes.
|
|
||||||
dst, err := libol.ParseNet(remote)
|
|
||||||
if err != nil {
|
|
||||||
return libol.NewErr("%s %s.", err, remote)
|
|
||||||
}
|
|
||||||
gw := libol.ParseAddr(src)
|
|
||||||
rte := &nl.Route{
|
|
||||||
Dst: dst,
|
|
||||||
Gw: gw,
|
|
||||||
LinkIndex: link.Attrs().Index,
|
|
||||||
Priority: 650,
|
|
||||||
AdvMSS: w.spec.TcpMss,
|
|
||||||
}
|
|
||||||
w.out.Debug("EspWorker.addRoute: %s", rte)
|
|
||||||
if err := nl.RouteReplace(rte); err != nil {
|
|
||||||
return libol.NewErr("%s %s.", err, remote)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) UpDummy(name, addr, peer string) error {
|
|
||||||
link, _ := nl.LinkByName(name)
|
|
||||||
if link == nil {
|
|
||||||
port := &nl.Dummy{
|
|
||||||
LinkAttrs: nl.LinkAttrs{
|
|
||||||
TxQLen: -1,
|
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := nl.LinkAdd(port); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
link, _ = nl.LinkByName(name)
|
|
||||||
}
|
|
||||||
if err := nl.LinkSetUp(link); err != nil {
|
|
||||||
w.out.Error("EspWorker.UpDummy: %s", err)
|
|
||||||
}
|
|
||||||
if addr != "" {
|
|
||||||
ipAddr, err := nl.ParseAddr(addr)
|
|
||||||
if err != nil {
|
|
||||||
return libol.NewErr("%s %s.", err, addr)
|
|
||||||
}
|
|
||||||
if err := nl.AddrReplace(link, ipAddr); err != nil {
|
|
||||||
w.out.Warn("EspWorker.UpDummy: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.out.Info("EspWorker.Open %s success", name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) addXfrm() {
|
|
||||||
for _, state := range w.states {
|
|
||||||
w.out.Debug("EspWorker.AddXfrm State %v", state)
|
|
||||||
if err := nl.XfrmStateAdd(state.In); err != nil {
|
|
||||||
w.out.Error("EspWorker.addXfrm in %s: %s", state.String(), err)
|
|
||||||
}
|
|
||||||
if err := nl.XfrmStateAdd(state.Out); err != nil {
|
|
||||||
w.out.Error("EspWorker.addXfrm out %s: %s", state.String(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, pol := range w.policies {
|
|
||||||
w.out.Debug("EspWorker.AddXfrm Policy %v", pol)
|
|
||||||
if err := nl.XfrmPolicyAdd(pol.In); err != nil {
|
|
||||||
w.out.Error("EspWorker.addXfrm in %v: %s", pol.In, err)
|
|
||||||
}
|
|
||||||
if err := nl.XfrmPolicyAdd(pol.Fwd); err != nil {
|
|
||||||
w.out.Error("EspWorker.addXfrm fwd %v: %s", pol.Fwd, err)
|
|
||||||
}
|
|
||||||
if err := nl.XfrmPolicyAdd(pol.Out); err != nil {
|
|
||||||
w.out.Error("EspWorker.addXfrm out %v: %s", pol.Out, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) Start(v api.Switcher) {
|
|
||||||
w.uuid = v.UUID()
|
|
||||||
w.upMember()
|
|
||||||
w.addXfrm()
|
|
||||||
cache.Esp.Add(&models.Esp{
|
|
||||||
Name: w.cfg.Name,
|
|
||||||
Address: w.spec.Address,
|
|
||||||
})
|
|
||||||
w.WorkerImpl.Start(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) DownDummy(name string) error {
|
|
||||||
link, _ := nl.LinkByName(name)
|
|
||||||
if link == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
port := &nl.Dummy{
|
|
||||||
LinkAttrs: nl.LinkAttrs{
|
|
||||||
TxQLen: -1,
|
|
||||||
Name: name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if err := nl.LinkDel(port); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) delXfrm() {
|
|
||||||
for _, mp := range w.policies {
|
|
||||||
w.delPolicy(mp)
|
|
||||||
if err := nl.XfrmPolicyDel(mp.In); err != nil {
|
|
||||||
w.out.Warn("EspWorker.delXfrm Policy.in %s: %s", mp.String(), err)
|
|
||||||
}
|
|
||||||
if err := nl.XfrmPolicyDel(mp.Fwd); err != nil {
|
|
||||||
w.out.Warn("EspWorker.delXfrm Policy.fwd %s: %s", mp.String(), err)
|
|
||||||
}
|
|
||||||
if err := nl.XfrmPolicyDel(mp.Out); err != nil {
|
|
||||||
w.out.Warn("EspWorker.delXfrm Policy.out %s: %s", mp.String(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.policies = nil
|
|
||||||
for _, ms := range w.states {
|
|
||||||
w.delState(ms)
|
|
||||||
if err := nl.XfrmStateDel(ms.In); err != nil {
|
|
||||||
w.out.Warn("EspWorker.delXfrm State.in %s: %s", ms.String(), err)
|
|
||||||
}
|
|
||||||
if err := nl.XfrmStateDel(ms.Out); err != nil {
|
|
||||||
w.out.Warn("EspWorker.delXfrm State.out %s: %s", ms.String(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.states = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) Stop() {
|
|
||||||
w.WorkerImpl.Stop()
|
|
||||||
cache.Esp.Del(w.cfg.Name)
|
|
||||||
w.downMember()
|
|
||||||
w.delXfrm()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) Reload(v api.Switcher) {
|
|
||||||
w.Stop()
|
|
||||||
w.Initialize()
|
|
||||||
w.Start(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) upMember() {
|
|
||||||
for _, mem := range w.spec.Members {
|
|
||||||
if mem.Peer == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := w.UpDummy(w.spec.Name, mem.Address, mem.Peer); err != nil {
|
|
||||||
w.out.Warn("EspWorker.UpDummy %d %s", mem.Spi, err)
|
|
||||||
}
|
|
||||||
for _, po := range mem.Policies {
|
|
||||||
if err := w.addRoute(w.spec.Name, mem.Address, po.Dest); err != nil {
|
|
||||||
w.out.Warn("EspWorker.addRoute %d %s", mem.Spi, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *EspWorker) downMember() {
|
|
||||||
for _, mem := range w.spec.Members {
|
|
||||||
if mem.Peer == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := w.DownDummy(w.spec.Name); err != nil {
|
|
||||||
w.out.Error("EspWorker.downMember %d %s", mem.Spi, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
package cswitch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDNS_lookup(t *testing.T) {
|
|
||||||
addr, err := net.LookupHost("nj.openlan.net")
|
|
||||||
fmt.Println(addr, err)
|
|
||||||
addr, err = net.LookupHost("114.221.197.118")
|
|
||||||
fmt.Println(addr, err)
|
|
||||||
}
|
|
@@ -1,209 +0,0 @@
|
|||||||
package cswitch
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
co "github.com/luscis/openlan/pkg/config"
|
|
||||||
"github.com/luscis/openlan/pkg/libol"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
L2TPBin = "xl2tpd"
|
|
||||||
L2TPDir = "/var/openlan/l2tp"
|
|
||||||
)
|
|
||||||
|
|
||||||
type L2TP struct {
|
|
||||||
cfg *co.L2TP
|
|
||||||
out *libol.SubLogger
|
|
||||||
uuid string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewL2TP(cfg *co.L2TP) *L2TP {
|
|
||||||
return &L2TP{
|
|
||||||
cfg: cfg,
|
|
||||||
out: libol.NewSubLogger("l2tp"),
|
|
||||||
uuid: "l2tp",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Initialize() {
|
|
||||||
if err := os.Mkdir(L2TPDir, 0600); err != nil {
|
|
||||||
d.out.Error("OpenVPN.Initialize %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Conf() *co.L2TP {
|
|
||||||
return d.cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) UUID() string {
|
|
||||||
return d.uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Path() string {
|
|
||||||
return L2TPBin
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) PidFile() string {
|
|
||||||
return filepath.Join(L2TPDir, d.uuid+".pid")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) ConfFile() string {
|
|
||||||
return filepath.Join(L2TPDir, d.uuid+".conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) OptionsFile() string {
|
|
||||||
return filepath.Join(L2TPDir, d.uuid+".options")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Tmpl() string {
|
|
||||||
return `
|
|
||||||
[global]
|
|
||||||
listen-addr = {{ .Listen }}
|
|
||||||
{{- if .Ipsec }}
|
|
||||||
ipsec saref = yes
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
[lns default]
|
|
||||||
ip range = {{ .StartAt }}-{{ .EndAt }}
|
|
||||||
local ip = {{ .Local }}
|
|
||||||
require chap = yes
|
|
||||||
refuse pap = yes
|
|
||||||
require authentication = yes
|
|
||||||
name = LinuxL2TP
|
|
||||||
ppp debug = yes
|
|
||||||
pppoptfile = {{ .Option }}
|
|
||||||
length bit = yes
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) OptionsTmpl() string {
|
|
||||||
return `
|
|
||||||
ipcp-accept-local
|
|
||||||
ipcp-accept-remote
|
|
||||||
noccp
|
|
||||||
# noauth
|
|
||||||
crtscts
|
|
||||||
mtu 1410
|
|
||||||
mru 1410
|
|
||||||
nodefaultroute
|
|
||||||
debug
|
|
||||||
lock
|
|
||||||
{{- range .Options }}
|
|
||||||
{{ . }}
|
|
||||||
{{- end }}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) SaveConf() {
|
|
||||||
fp, err := libol.CreateFile(d.ConfFile())
|
|
||||||
if err != nil || fp == nil {
|
|
||||||
libol.Error("L2TP.SaveConf: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer fp.Close()
|
|
||||||
|
|
||||||
cfg := d.cfg
|
|
||||||
tmpl := d.Tmpl()
|
|
||||||
data := struct {
|
|
||||||
Listen string
|
|
||||||
Local string
|
|
||||||
StartAt string
|
|
||||||
EndAt string
|
|
||||||
Option string
|
|
||||||
Ipsec bool
|
|
||||||
}{
|
|
||||||
Listen: "0.0.0.0",
|
|
||||||
Local: cfg.Address,
|
|
||||||
StartAt: cfg.Subnet.Start,
|
|
||||||
EndAt: cfg.Subnet.End,
|
|
||||||
Option: d.OptionsFile(),
|
|
||||||
}
|
|
||||||
if cfg.IpSec == "enable" {
|
|
||||||
data.Ipsec = true
|
|
||||||
}
|
|
||||||
d.Render(fp, tmpl, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Render(fp *os.File, tmpl string, data interface{}) {
|
|
||||||
if tmpl, err := template.New("main").Parse(tmpl); err == nil {
|
|
||||||
if err := tmpl.Execute(fp, data); err != nil {
|
|
||||||
d.out.Warn("L2TP.Render: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d.out.Warn("L2TP.Render: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) SaveOptions() {
|
|
||||||
fp, err := libol.CreateFile(d.OptionsFile())
|
|
||||||
if err != nil || fp == nil {
|
|
||||||
libol.Error("L2TP.SaveOptions: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer fp.Close()
|
|
||||||
|
|
||||||
cfg := d.cfg
|
|
||||||
tmpl := d.OptionsTmpl()
|
|
||||||
data := struct {
|
|
||||||
Options []string
|
|
||||||
}{
|
|
||||||
Options: cfg.Options,
|
|
||||||
}
|
|
||||||
d.Render(fp, tmpl, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Start() {
|
|
||||||
if d.cfg.Subnet == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.SaveConf()
|
|
||||||
d.SaveOptions()
|
|
||||||
libol.Go(func() {
|
|
||||||
args := []string{
|
|
||||||
"-c", d.ConfFile(),
|
|
||||||
"-p", d.PidFile(),
|
|
||||||
"-D",
|
|
||||||
}
|
|
||||||
d.out.Info("L2TP.Start %s %v", d.Path(), args)
|
|
||||||
cmd := exec.Command(d.Path(), args...)
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
d.out.Error("L2TP.Start %s: %s", d.uuid, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Clean() {
|
|
||||||
files := []string{
|
|
||||||
d.PidFile(), d.ConfFile(),
|
|
||||||
}
|
|
||||||
for _, file := range files {
|
|
||||||
if err := libol.FileExist(file); err == nil {
|
|
||||||
if err := os.Remove(file); err != nil {
|
|
||||||
d.out.Warn("L2TP.Clean %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *L2TP) Stop() {
|
|
||||||
if d.cfg.Subnet == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if data, err := ioutil.ReadFile(d.PidFile()); err != nil {
|
|
||||||
d.out.Info("L2TP.Stop %s", err)
|
|
||||||
} else {
|
|
||||||
pid := strings.TrimSpace(string(data))
|
|
||||||
cmd := exec.Command("/usr/bin/kill", pid)
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
d.out.Warn("L2TP.Stop %s: %s", pid, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.Clean()
|
|
||||||
}
|
|
@@ -19,12 +19,8 @@ import (
|
|||||||
func NewNetworker(c *co.Network) api.Networker {
|
func NewNetworker(c *co.Network) api.Networker {
|
||||||
var obj api.Networker
|
var obj api.Networker
|
||||||
switch c.Provider {
|
switch c.Provider {
|
||||||
case "esp":
|
|
||||||
obj = NewESPWorker(c)
|
|
||||||
case "vxlan":
|
case "vxlan":
|
||||||
obj = NewVxLANWorker(c)
|
obj = NewVxLANWorker(c)
|
||||||
case "fabric":
|
|
||||||
obj = NewFabricWorker(c)
|
|
||||||
case "router":
|
case "router":
|
||||||
obj = NewRouterWorker(c)
|
obj = NewRouterWorker(c)
|
||||||
default:
|
default:
|
||||||
|
@@ -3,8 +3,6 @@ package cswitch
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -102,8 +100,6 @@ type Switch struct {
|
|||||||
uuid string
|
uuid string
|
||||||
newTime int64
|
newTime int64
|
||||||
out *libol.SubLogger
|
out *libol.SubLogger
|
||||||
confd *ConfD
|
|
||||||
l2tp *L2TP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSwitch(c *co.Switch) *Switch {
|
func NewSwitch(c *co.Switch) *Switch {
|
||||||
@@ -117,7 +113,6 @@ func NewSwitch(c *co.Switch) *Switch {
|
|||||||
hooks: make([]Hook, 0, 64),
|
hooks: make([]Hook, 0, 64),
|
||||||
out: libol.NewSubLogger(c.Alias),
|
out: libol.NewSubLogger(c.Alias),
|
||||||
}
|
}
|
||||||
v.confd = NewConfd(v)
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,8 +210,8 @@ func (v *Switch) GetPort(listen string) string {
|
|||||||
|
|
||||||
func (v *Switch) openPorts() {
|
func (v *Switch) openPorts() {
|
||||||
port := v.GetPort(v.cfg.Listen)
|
port := v.GetPort(v.cfg.Listen)
|
||||||
UdpPorts := []string{"4500", "4500", "8472", "4789", port}
|
UdpPorts := []string{"500", "4500", "8472", "4789", port}
|
||||||
TcpPorts := []string{"7471", port}
|
TcpPorts := []string{"10000", port}
|
||||||
if v.cfg.Http != nil {
|
if v.cfg.Http != nil {
|
||||||
TcpPorts = append(TcpPorts, v.GetPort(v.cfg.Http.Listen))
|
TcpPorts = append(TcpPorts, v.GetPort(v.cfg.Http.Listen))
|
||||||
}
|
}
|
||||||
@@ -287,12 +282,6 @@ func (v *Switch) Initialize() {
|
|||||||
Crt: cert.CrtFile,
|
Crt: cert.CrtFile,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Enable L2TP
|
|
||||||
if v.cfg.L2TP != nil {
|
|
||||||
v.l2tp = NewL2TP(v.cfg.L2TP)
|
|
||||||
}
|
|
||||||
// Start confd monitor
|
|
||||||
v.confd.Initialize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Switch) onFrame(client libol.SocketClient, frame *libol.FrameMessage) error {
|
func (v *Switch) onFrame(client libol.SocketClient, frame *libol.FrameMessage) error {
|
||||||
@@ -394,18 +383,6 @@ func (v *Switch) OnClose(client libol.SocketClient) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Switch) openUdp() {
|
|
||||||
args := []string{
|
|
||||||
"-port", strconv.Itoa(co.EspLocalUdp),
|
|
||||||
"-log:file", "/var/openlan/openudp.log",
|
|
||||||
}
|
|
||||||
libol.Info("%s %v", UDPBin, args)
|
|
||||||
cmd := exec.Command(UDPBin, args...)
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
libol.Error("Switch.OpenUdp %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Switch) Start() {
|
func (v *Switch) Start() {
|
||||||
v.lock.Lock()
|
v.lock.Lock()
|
||||||
defer v.lock.Unlock()
|
defer v.lock.Unlock()
|
||||||
@@ -429,11 +406,6 @@ func (v *Switch) Start() {
|
|||||||
if v.http != nil {
|
if v.http != nil {
|
||||||
libol.Go(v.http.Start)
|
libol.Go(v.http.Start)
|
||||||
}
|
}
|
||||||
libol.Go(v.confd.Start)
|
|
||||||
if v.l2tp != nil {
|
|
||||||
libol.Go(v.l2tp.Start)
|
|
||||||
}
|
|
||||||
libol.Go(v.openUdp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Switch) Stop() {
|
func (v *Switch) Stop() {
|
||||||
@@ -442,10 +414,6 @@ func (v *Switch) Stop() {
|
|||||||
|
|
||||||
v.out.Info("Switch.Stop")
|
v.out.Info("Switch.Stop")
|
||||||
|
|
||||||
if v.l2tp != nil {
|
|
||||||
v.l2tp.Stop()
|
|
||||||
}
|
|
||||||
v.confd.Stop()
|
|
||||||
if v.http != nil {
|
if v.http != nil {
|
||||||
v.http.Shutdown()
|
v.http.Shutdown()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user