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"
|
||||
|
||||
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-proxy ./cmd/proxy
|
||||
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)/pkg/public $(LIN_DIR)/var/openlan
|
||||
@mkdir -p $(LIN_DIR)/usr/bin
|
||||
@cp -rf $(BD)/{openudp,openlan} $(LIN_DIR)/usr/bin
|
||||
@cp -rf $(BD)/{openlan-point,openlan-proxy,openlan-switch} $(LIN_DIR)/usr/bin
|
||||
@cp -rf $(BD)/{openlan,openlan-switch} $(LIN_DIR)/usr/bin
|
||||
@cp -rf $(BD)/{openlan-point,openlan-proxy} $(LIN_DIR)/usr/bin
|
||||
@echo "Installed to $(LIN_DIR)"
|
||||
|
||||
## cross build for windows
|
||||
|
55
README.cn.md
55
README.cn.md
@@ -67,65 +67,10 @@ OpenLAN提供一种局域网数据报文在广域网的传输实现,并能够
|
||||
OpenLAN OpenLAN OpenLAN
|
||||
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/central.md)
|
||||
- [多区域互联](docs/multiarea.md)
|
||||
- [全互连网络](docs/fabric.md)
|
||||
- [IPSec网络](docs/ipsec.md)
|
||||
- [零信任网络](docs/ztrust.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
|
||||
|
||||
|
||||
### 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
|
||||
- [Software Installation](docs/install.md)
|
||||
- [Branch Access](docs/central.md)
|
||||
- [Multi-region Interconnection](docs/multiarea.md)
|
||||
- [Fullly Interconnected Network](docs/fabric.md)
|
||||
- [IPSec Network](docs/ipsec.md)
|
||||
- [Zero Trust Network](docs/ztrust.md)
|
||||
- [Docker Compose](docs/docker.md)
|
||||
|
@@ -39,10 +39,7 @@ func Commands(app *api.App) {
|
||||
Server{}.Commands(app)
|
||||
Network{}.Commands(app)
|
||||
PProf{}.Commands(app)
|
||||
Esp{}.Commands(app)
|
||||
VxLAN{}.Commands(app)
|
||||
State{}.Commands(app)
|
||||
Policy{}.Commands(app)
|
||||
Version{}.Commands(app)
|
||||
Log{}.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 (
|
||||
"log"
|
||||
|
||||
"github.com/luscis/openlan/cmd/api"
|
||||
"github.com/luscis/openlan/pkg/cache"
|
||||
"github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
@@ -12,9 +11,6 @@ import (
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
udp := api.GetEnv("ESPUDP", "4500")
|
||||
|
||||
config.SetLocalUdp(udp)
|
||||
c := config.NewSwitch()
|
||||
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,
|
||||
"remote": "enp2s2"
|
||||
},
|
||||
{
|
||||
"segment": 44,
|
||||
"remote": "3.3.3.6",
|
||||
"protocol": "vxlan",
|
||||
"secret": "swordfish"
|
||||
}
|
||||
]
|
@@ -15,17 +15,5 @@
|
||||
"baseDN": "dc=openlan,dc=com",
|
||||
"attribute": "cn",
|
||||
"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 ..."
|
||||
if [ "$OS"x == "centos"x ]; then
|
||||
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
|
||||
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
|
||||
echo "We didn't find any packet tool: $OS"
|
||||
fi
|
||||
@@ -42,6 +42,7 @@ function install() {
|
||||
local source=$(find $tmp -maxdepth 1 -name 'openlan-*')
|
||||
cd $source && {
|
||||
/usr/bin/env \cp -rf ./{etc,usr,var} /
|
||||
chmod +x /var/openlan/script/*.sh
|
||||
/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
|
||||
update-ca-certificates
|
||||
fi
|
||||
## Initialize NSS database
|
||||
certutil -N -d sql:/var/lib/ipsec/nss --empty-password
|
||||
}
|
||||
|
||||
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"
|
||||
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:
|
||||
restart: always
|
||||
image: "luscis/openlan:latest.x86_64"
|
||||
@@ -8,6 +16,9 @@ services:
|
||||
entrypoint: ["/var/openlan/script/switch.sh", "start"]
|
||||
volumes:
|
||||
- /opt/openlan/etc/openlan:/etc/openlan
|
||||
- /opt/openlan/etc/ipsecd.d:/etc/ipsec.d
|
||||
depends_on:
|
||||
- ipsec
|
||||
proxy:
|
||||
restart: always
|
||||
image: "luscis/openlan:latest.x86_64"
|
||||
@@ -17,3 +28,7 @@ services:
|
||||
- /opt/openlan/etc/openlan:/etc/openlan
|
||||
depends_on:
|
||||
- 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)
|
||||
PProf{}.Router(router)
|
||||
VxLAN{}.Router(router)
|
||||
Esp{}.Router(router)
|
||||
EspState{}.Router(router)
|
||||
EspPolicy{}.Router(router)
|
||||
Config{Switcher: switcher}.Router(router)
|
||||
Version{}.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)
|
||||
Online.Init(cfg.OnLine)
|
||||
User.Init(cfg.User)
|
||||
Esp.Init(cfg.Esp)
|
||||
EspState.Init(cfg.State)
|
||||
EspPolicy.Init(cfg.Policy)
|
||||
}
|
||||
|
||||
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 (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/luscis/openlan/pkg/config"
|
||||
"github.com/luscis/openlan/pkg/libol"
|
||||
"github.com/luscis/openlan/pkg/models"
|
||||
"github.com/luscis/openlan/pkg/schema"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type SocketClientMock struct {
|
||||
@@ -28,31 +28,4 @@ func TestInit(t *testing.T) {
|
||||
Client: &SocketClientMock{},
|
||||
})
|
||||
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{} {
|
||||
switch n.Provider {
|
||||
case "esp":
|
||||
n.Specifies = &EspSpecifies{}
|
||||
case "vxlan":
|
||||
n.Specifies = &VxLANSpecifies{}
|
||||
case "fabric":
|
||||
n.Specifies = &FabricSpecifies{}
|
||||
case "router":
|
||||
n.Specifies = &RouterSpecifies{}
|
||||
default:
|
||||
@@ -53,25 +49,6 @@ func (n *Network) Correct(sw *Switch) {
|
||||
br.Network = n.Name
|
||||
br.Correct()
|
||||
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":
|
||||
spec := n.Specifies
|
||||
if obj, ok := spec.(*RouterSpecifies); ok {
|
||||
@@ -201,11 +178,4 @@ func (n *Network) SaveNextGroup() {
|
||||
}
|
||||
|
||||
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"`
|
||||
ConfDir string `json:"-"`
|
||||
TokenFile string `json:"-"`
|
||||
L2TP *L2TP `json:"l2tp"`
|
||||
}
|
||||
|
||||
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="panel-header">
|
||||
<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 class="panel-body">
|
||||
@@ -150,37 +150,21 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .Outputs }}
|
||||
<tr>
|
||||
<td>output</td>
|
||||
<td>{{ prettyTime .AliveTime }}</td>
|
||||
<td>{{ .Device }}</td>
|
||||
<td>ID:{{ .Segment }}</td>
|
||||
<td>{{ .Protocol }}</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 .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>
|
||||
{{ range .Outputs }}
|
||||
<tr>
|
||||
<td>output</td>
|
||||
<td>{{ prettyTime .AliveTime }}</td>
|
||||
<td>{{ .Device }}</td>
|
||||
<td>ID:{{ .Segment }}</td>
|
||||
<td>{{ .Protocol }}</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 }}
|
||||
<tr>
|
||||
|
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
|
||||
})
|
||||
}
|
||||
// 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
|
||||
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 {
|
||||
var obj api.Networker
|
||||
switch c.Provider {
|
||||
case "esp":
|
||||
obj = NewESPWorker(c)
|
||||
case "vxlan":
|
||||
obj = NewVxLANWorker(c)
|
||||
case "fabric":
|
||||
obj = NewFabricWorker(c)
|
||||
case "router":
|
||||
obj = NewRouterWorker(c)
|
||||
default:
|
||||
|
@@ -3,8 +3,6 @@ package cswitch
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -102,8 +100,6 @@ type Switch struct {
|
||||
uuid string
|
||||
newTime int64
|
||||
out *libol.SubLogger
|
||||
confd *ConfD
|
||||
l2tp *L2TP
|
||||
}
|
||||
|
||||
func NewSwitch(c *co.Switch) *Switch {
|
||||
@@ -117,7 +113,6 @@ func NewSwitch(c *co.Switch) *Switch {
|
||||
hooks: make([]Hook, 0, 64),
|
||||
out: libol.NewSubLogger(c.Alias),
|
||||
}
|
||||
v.confd = NewConfd(v)
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -215,8 +210,8 @@ func (v *Switch) GetPort(listen string) string {
|
||||
|
||||
func (v *Switch) openPorts() {
|
||||
port := v.GetPort(v.cfg.Listen)
|
||||
UdpPorts := []string{"4500", "4500", "8472", "4789", port}
|
||||
TcpPorts := []string{"7471", port}
|
||||
UdpPorts := []string{"500", "4500", "8472", "4789", port}
|
||||
TcpPorts := []string{"10000", port}
|
||||
if v.cfg.Http != nil {
|
||||
TcpPorts = append(TcpPorts, v.GetPort(v.cfg.Http.Listen))
|
||||
}
|
||||
@@ -287,12 +282,6 @@ func (v *Switch) Initialize() {
|
||||
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 {
|
||||
@@ -394,18 +383,6 @@ func (v *Switch) OnClose(client libol.SocketClient) error {
|
||||
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() {
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
@@ -429,11 +406,6 @@ func (v *Switch) Start() {
|
||||
if v.http != nil {
|
||||
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() {
|
||||
@@ -442,10 +414,6 @@ func (v *Switch) Stop() {
|
||||
|
||||
v.out.Info("Switch.Stop")
|
||||
|
||||
if v.l2tp != nil {
|
||||
v.l2tp.Stop()
|
||||
}
|
||||
v.confd.Stop()
|
||||
if v.http != nil {
|
||||
v.http.Shutdown()
|
||||
}
|
||||
|
Reference in New Issue
Block a user