fea: discard l2tp, esp, and fabric support.

This commit is contained in:
Daniel Ding
2024-06-07 19:25:21 +08:00
parent f2f6323284
commit 0fc0ee6d6f
47 changed files with 58 additions and 3238 deletions

View File

@@ -101,7 +101,6 @@ docker-compose: ## create a compose files
echo "$ docker-compose up -d" echo "$ docker-compose up -d"
linux: env ## build linux binary linux: env ## build linux binary
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openudp ./cmd/openudp
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan ./cmd/main.go go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan ./cmd/main.go
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-proxy ./cmd/proxy go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-proxy ./cmd/proxy
go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-point ./cmd/point_linux go build -mod=vendor -ldflags "$(LDFLAGS)" -o $(BD)/openlan-point ./cmd/point_linux
@@ -128,8 +127,8 @@ install: env linux ## install packages
@cp -rf $(SD)/dist/cert/openlan/ca/ca.crt $(LIN_DIR)/var/openlan/cert @cp -rf $(SD)/dist/cert/openlan/ca/ca.crt $(LIN_DIR)/var/openlan/cert
@cp -rf $(SD)/pkg/public $(LIN_DIR)/var/openlan @cp -rf $(SD)/pkg/public $(LIN_DIR)/var/openlan
@mkdir -p $(LIN_DIR)/usr/bin @mkdir -p $(LIN_DIR)/usr/bin
@cp -rf $(BD)/{openudp,openlan} $(LIN_DIR)/usr/bin @cp -rf $(BD)/{openlan,openlan-switch} $(LIN_DIR)/usr/bin
@cp -rf $(BD)/{openlan-point,openlan-proxy,openlan-switch} $(LIN_DIR)/usr/bin @cp -rf $(BD)/{openlan-point,openlan-proxy} $(LIN_DIR)/usr/bin
@echo "Installed to $(LIN_DIR)" @echo "Installed to $(LIN_DIR)"
## cross build for windows ## cross build for windows

View File

@@ -67,65 +67,10 @@ OpenLAN提供一种局域网数据报文在广域网的传输实现并能够
OpenLAN OpenLAN OpenLAN OpenLAN OpenLAN OpenLAN
192.168.1.11/24 192.168.1.12/24 192.168.1.13/24 192.168.1.11/24 192.168.1.12/24 192.168.1.13/24
### 数据中心全互联网络
* Underlay for VxLAN over Internet by IPSec.
47.example.com
|
|
|
+-------+
| vps-47| -- 100.65.0.117
+-------+
/ \
/ \
SPI-117118 / \ SPI-117119
/ \
/ \
+-------+ +-------+
| vps-92| -------------- | vps-12|
+-------+ +-------+
/ | | \
/ | SPI-118119 | \
100.65.0.118 | | 100.65.0.119
| |
92.example.com 12.example.com
* DCI Subnet: 192.168.x.x over IPSec Network: 100.65.0.x.
100.65.0.117
|
eth1.200 --- | --- eth1.100
\ | /
+--------+
| vps-47 |
+--------+
/ \
/ \
/ \
/ \
enp2s4.100 --- / \ --- eth4.30
\ / \ /
+--------+ +--------+
| vps-92 | --------------- | vps-12 |
+--------+ +--------+
/ | | \
enp2s4.101 --- | | --- eth4.200
| |
100.65.0.118 100.65.0.119
VNI-1023 192.168.30.0/24 [vps-47_eth1.100, vps-92_enp2s4.100, vps-12_eth4.30]
VNI-1024 192.168.40.0/24 [vps-47_eth1.200, vps-92_enp2s4.101, vps-12_eth4.200]
## 帮助文档 ## 帮助文档
- [软件安装](docs/install.md) - [软件安装](docs/install.md)
- [分支接入](docs/central.md) - [分支接入](docs/central.md)
- [多区域互联](docs/multiarea.md) - [多区域互联](docs/multiarea.md)
- [全互连网络](docs/fabric.md)
- [IPSec网络](docs/ipsec.md)
- [零信任网络](docs/ztrust.md) - [零信任网络](docs/ztrust.md)
- [Docker Compose](docs/docker.md) - [Docker Compose](docs/docker.md)

View File

@@ -65,64 +65,9 @@ If you have more flexible VPN business needs and need to use VPN to access the e
192.168.1.11/24 192.168.1.12/24 192.168.1.13/24 192.168.1.11/24 192.168.1.12/24 192.168.1.13/24
### Data Center Full Internet
* Underlay for VxLAN over Internet by IPSec.
47.example.com
|
|
|
+-------+
| vps-47| -- 100.65.0.117
+-------+
/ \
/ \
SPI-117118 / \ SPI-117119
/ \
/ \
+-------+ +-------+
| vps-92| -------------- | vps-12|
+-------+ +-------+
/ | | \
/ | SPI-118119 | \
100.65.0.118 | | 100.65.0.119
| |
92.example.com 12.example.com
* DCI Subnet: 192.168.x.x over IPSec Network: 100.65.0.x.
100.65.0.117
|
eth1.200 --- | --- eth1.100
\ | /
+--------+
| vps-47 |
+--------+
/ \
/ \
/ \
/ \
enp2s4.100 --- / \ --- eth4.30
\ / \ /
+--------+ +--------+
| vps-92 | --------------- | vps-12 |
+--------+ +--------+
/ | | \
enp2s4.101 --- | | --- eth4.200
| |
100.65.0.118 100.65.0.119
VNI-1023 192.168.30.0/24 [vps-47_eth1.100, vps-92_enp2s4.100, vps-12_eth4.30]
VNI-1024 192.168.40.0/24 [vps-47_eth1.200, vps-92_enp2s4.101, vps-12_eth4.200]
## Help documents ## Help documents
- [Software Installation](docs/install.md) - [Software Installation](docs/install.md)
- [Branch Access](docs/central.md) - [Branch Access](docs/central.md)
- [Multi-region Interconnection](docs/multiarea.md) - [Multi-region Interconnection](docs/multiarea.md)
- [Fullly Interconnected Network](docs/fabric.md)
- [IPSec Network](docs/ipsec.md)
- [Zero Trust Network](docs/ztrust.md) - [Zero Trust Network](docs/ztrust.md)
- [Docker Compose](docs/docker.md) - [Docker Compose](docs/docker.md)

View File

@@ -39,10 +39,7 @@ func Commands(app *api.App) {
Server{}.Commands(app) Server{}.Commands(app)
Network{}.Commands(app) Network{}.Commands(app)
PProf{}.Commands(app) PProf{}.Commands(app)
Esp{}.Commands(app)
VxLAN{}.Commands(app) VxLAN{}.Commands(app)
State{}.Commands(app)
Policy{}.Commands(app)
Version{}.Commands(app) Version{}.Commands(app)
Log{}.Commands(app) Log{}.Commands(app)
Guest{}.Commands(app) Guest{}.Commands(app)

View File

@@ -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,
},
},
})
}

View File

@@ -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,
},
},
})
}

View File

@@ -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,
},
},
})
}

View File

@@ -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()
}

View File

@@ -3,7 +3,6 @@ package main
import ( import (
"log" "log"
"github.com/luscis/openlan/cmd/api"
"github.com/luscis/openlan/pkg/cache" "github.com/luscis/openlan/pkg/cache"
"github.com/luscis/openlan/pkg/config" "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol" "github.com/luscis/openlan/pkg/libol"
@@ -12,9 +11,6 @@ import (
func main() { func main() {
log.SetFlags(0) log.SetFlags(0)
udp := api.GetEnv("ESPUDP", "4500")
config.SetLocalUdp(udp)
c := config.NewSwitch() c := config.NewSwitch()
config.Update(c) config.Update(c)

View File

@@ -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

View File

@@ -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"
}
]
}
}

View File

@@ -1,4 +0,0 @@
{
"name": "ipsec",
"provider": "esp"
}

View File

@@ -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"
}
]
}
]
}
}

View File

@@ -13,5 +13,11 @@
{ {
"segment": 23, "segment": 23,
"remote": "enp2s2" "remote": "enp2s2"
},
{
"segment": 44,
"remote": "3.3.3.6",
"protocol": "vxlan",
"secret": "swordfish"
} }
] ]

View File

@@ -15,17 +15,5 @@
"baseDN": "dc=openlan,dc=com", "baseDN": "dc=openlan,dc=com",
"attribute": "cn", "attribute": "cn",
"filter": "(cn=%s)" "filter": "(cn=%s)"
},
"l2tp": {
"ipsec": "enable",
"address": "192.168.33.1",
"subnet": {
"startAt": "192.168.33.100",
"endAt": "192.168.33.250"
},
"options": [
"ms-dns 8.8.8.8",
"ms-dns 8.8.4.4"
]
} }
} }

View File

@@ -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

View File

@@ -28,10 +28,10 @@ function requires() {
echo "Install dependents ..." echo "Install dependents ..."
if [ "$OS"x == "centos"x ]; then if [ "$OS"x == "centos"x ]; then
yum install -y openssl net-tools iptables iputils iperf3 tcpdump yum install -y openssl net-tools iptables iputils iperf3 tcpdump
yum install -y openvpn openvswitch dnsmasq bridge-utils ipset yum install -y openvpn dnsmasq bridge-utils ipset libreswan procps
elif [ "$OS"x == "ubuntu"x ]; then elif [ "$OS"x == "ubuntu"x ]; then
apt-get install -y net-tools iptables iproute2 tcpdump ca-certificates iperf3 apt-get install -y net-tools iptables iproute2 tcpdump ca-certificates iperf3
apt-get install -y openvpn openvswitch-switch dnsmasq bridge-utils ipset apt-get install -y openvpn dnsmasq bridge-utils ipset libreswan procps
else else
echo "We didn't find any packet tool: $OS" echo "We didn't find any packet tool: $OS"
fi fi
@@ -42,6 +42,7 @@ function install() {
local source=$(find $tmp -maxdepth 1 -name 'openlan-*') local source=$(find $tmp -maxdepth 1 -name 'openlan-*')
cd $source && { cd $source && {
/usr/bin/env \cp -rf ./{etc,usr,var} / /usr/bin/env \cp -rf ./{etc,usr,var} /
chmod +x /var/openlan/script/*.sh
/usr/bin/env find ./ -type f > /usr/share/openlan.db /usr/bin/env find ./ -type f > /usr/share/openlan.db
} }
} }
@@ -68,6 +69,8 @@ function post() {
cp -rf /var/openlan/cert/ca.crt /usr/local/share/ca-certificates/OpenLAN_CA.crt cp -rf /var/openlan/cert/ca.crt /usr/local/share/ca-certificates/OpenLAN_CA.crt
update-ca-certificates update-ca-certificates
fi fi
## Initialize NSS database
certutil -N -d sql:/var/lib/ipsec/nss --empty-password
} }
function finish() { function finish() {

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +1,13 @@
version: "2.3" version: "2.3"
services: services:
ipsec:
restart: always
image: "luscis/openlan:latest.x86_64"
privileged: true
network_mode: host
entrypoint: ["/var/openlan/script/ipsec.sh"]
volumes:
- /opt/openlan/etc/ipsecd.d:/etc/ipsec.d
switch: switch:
restart: always restart: always
image: "luscis/openlan:latest.x86_64" image: "luscis/openlan:latest.x86_64"
@@ -8,6 +16,9 @@ services:
entrypoint: ["/var/openlan/script/switch.sh", "start"] entrypoint: ["/var/openlan/script/switch.sh", "start"]
volumes: volumes:
- /opt/openlan/etc/openlan:/etc/openlan - /opt/openlan/etc/openlan:/etc/openlan
- /opt/openlan/etc/ipsecd.d:/etc/ipsec.d
depends_on:
- ipsec
proxy: proxy:
restart: always restart: always
image: "luscis/openlan:latest.x86_64" image: "luscis/openlan:latest.x86_64"
@@ -16,4 +27,8 @@ services:
volumes: volumes:
- /opt/openlan/etc/openlan:/etc/openlan - /opt/openlan/etc/openlan:/etc/openlan
depends_on: depends_on:
- switch - switch
exporter:
restart: always
image: "prom/node-exporter:v1.7.0"
network_mode: host

View File

@@ -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]#
```

View File

@@ -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
```

View File

@@ -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)
}

View File

@@ -15,9 +15,6 @@ func Add(router *mux.Router, switcher Switcher) {
VPNClient{}.Router(router) VPNClient{}.Router(router)
PProf{}.Router(router) PProf{}.Router(router)
VxLAN{}.Router(router) VxLAN{}.Router(router)
Esp{}.Router(router)
EspState{}.Router(router)
EspPolicy{}.Router(router)
Config{Switcher: switcher}.Router(router) Config{Switcher: switcher}.Router(router)
Version{}.Router(router) Version{}.Router(router)
Log{}.Router(router) Log{}.Router(router)

141
pkg/cache/ipsec.go vendored
View File

@@ -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
View File

@@ -10,12 +10,7 @@ func Init(cfg *config.Perf) {
Neighbor.Init(cfg.Neighbor) Neighbor.Init(cfg.Neighbor)
Online.Init(cfg.OnLine) Online.Init(cfg.OnLine)
User.Init(cfg.User) User.Init(cfg.User)
Esp.Init(cfg.Esp)
EspState.Init(cfg.State)
EspPolicy.Init(cfg.Policy)
} }
func Reload() { func Reload() {
EspState.Clear()
EspPolicy.Clear()
} }

View File

@@ -2,12 +2,12 @@ package cache
import ( import (
"fmt" "fmt"
"testing"
"github.com/luscis/openlan/pkg/config" "github.com/luscis/openlan/pkg/config"
"github.com/luscis/openlan/pkg/libol" "github.com/luscis/openlan/pkg/libol"
"github.com/luscis/openlan/pkg/models" "github.com/luscis/openlan/pkg/models"
"github.com/luscis/openlan/pkg/schema"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"testing"
) )
type SocketClientMock struct { type SocketClientMock struct {
@@ -28,31 +28,4 @@ func TestInit(t *testing.T) {
Client: &SocketClientMock{}, Client: &SocketClientMock{},
}) })
assert.Equal(t, 1, Point.Clients.Len(), "MUST be same") assert.Equal(t, 1, Point.Clients.Len(), "MUST be same")
EspState.Add(&models.EspState{
EspState: &schema.EspState{},
})
assert.Equal(t, 1, EspState.State.Len(), "MUST be same")
User.Add(&models.User{
Alias: "fake",
})
assert.Equal(t, 1, User.Users.Len(), "MUST be same")
Link.Add("fake-uuid", &models.Link{
User: "fake",
})
assert.Equal(t, 1, Link.Links.Len(), "MUST be same")
EspPolicy.Add(&models.EspPolicy{
EspPolicy: &schema.EspPolicy{},
})
assert.Equal(t, 1, EspPolicy.Policy.Len(), "MUST be same")
Online.Add(&models.Line{
EthType: 0,
})
assert.Equal(t, 1, Online.Lines.Len(), "MUST be same")
Neighbor.Add(&models.Neighbor{
Network: "fake",
})
assert.Equal(t, 1, Neighbor.Neighbors.Len(), "MUST be same")
Reload()
assert.Equal(t, 0, EspState.State.Len(), "MUST be same")
assert.Equal(t, 0, EspPolicy.Policy.Len(), "MUST be same")
} }

View File

@@ -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
}

View File

@@ -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.")
}
}

View File

@@ -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"`
}

View File

@@ -31,12 +31,8 @@ type Network struct {
func (n *Network) NewSpecifies() interface{} { func (n *Network) NewSpecifies() interface{} {
switch n.Provider { switch n.Provider {
case "esp":
n.Specifies = &EspSpecifies{}
case "vxlan": case "vxlan":
n.Specifies = &VxLANSpecifies{} n.Specifies = &VxLANSpecifies{}
case "fabric":
n.Specifies = &FabricSpecifies{}
case "router": case "router":
n.Specifies = &RouterSpecifies{} n.Specifies = &RouterSpecifies{}
default: default:
@@ -53,25 +49,6 @@ func (n *Network) Correct(sw *Switch) {
br.Network = n.Name br.Network = n.Name
br.Correct() br.Correct()
switch n.Provider { switch n.Provider {
case "esp":
spec := n.Specifies
if obj, ok := spec.(*EspSpecifies); ok {
obj.Correct()
obj.Name = n.Name
}
case "fabric":
// 28 [udp] - 8 [esp] -
// 28 [udp] - 8 [vxlan] -
// 14 [ethernet] - tcp [40] - 1332 [mss] -
// 42 [padding] ~= variable 30-45
if br.Mss == 0 {
br.Mss = 1332
}
spec := n.Specifies
if obj, ok := spec.(*FabricSpecifies); ok {
obj.Correct()
obj.Name = n.Name
}
case "router": case "router":
spec := n.Specifies spec := n.Specifies
if obj, ok := spec.(*RouterSpecifies); ok { if obj, ok := spec.(*RouterSpecifies); ok {
@@ -201,11 +178,4 @@ func (n *Network) SaveNextGroup() {
} }
func (n *Network) Reload() { func (n *Network) Reload() {
switch n.Provider {
case "esp":
spec := n.Specifies
if obj, ok := spec.(*EspSpecifies); ok {
obj.Correct()
}
}
} }

View File

@@ -70,7 +70,6 @@ type Switch struct {
AddrPool string `json:"pool,omitempty"` AddrPool string `json:"pool,omitempty"`
ConfDir string `json:"-"` ConfDir string `json:"-"`
TokenFile string `json:"-"` TokenFile string `json:"-"`
L2TP *L2TP `json:"l2tp"`
} }
func NewSwitch() *Switch { func NewSwitch() *Switch {

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -132,7 +132,7 @@
<div class="link"> <div class="link">
<div class="panel-header"> <div class="panel-header">
<div> <div>
<span>The link which connect to other, and total </span><span>{{ len .States }}+{{ len .Links }}</span>. <span>The link which connect to other, and total </span><span>{{ len .Links }}</span>.
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
@@ -150,37 +150,21 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{ range .Outputs }} {{ range .Outputs }}
<tr> <tr>
<td>output</td> <td>output</td>
<td>{{ prettyTime .AliveTime }}</td> <td>{{ prettyTime .AliveTime }}</td>
<td>{{ .Device }}</td> <td>{{ .Device }}</td>
<td>ID:{{ .Segment }}</td> <td>ID:{{ .Segment }}</td>
<td>{{ .Protocol }}</td> <td>{{ .Protocol }}</td>
<td><a href="https://{{ .Remote }}:10000">{{ .Remote }}</a></td> <td><a href="https://{{ .Remote }}:10000">{{ .Remote }}</a></td>
<td>{{ .RxBytes }} | {{ .TxBytes }}</td> <td>{{ .RxBytes }} | {{ .TxBytes }}</td>
<td> <td>
{{ if .RxBytes }}<span class="success">success</span> {{ if .RxBytes }}<span class="success">success</span>
{{ else }}<span class="unknown">unknown</span> {{ else }}<span class="unknown">unknown</span>
{{ end}} {{ end}}
</td> </td>
</tr> </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>
{{ end }} {{ end }}
{{ range .Links }} {{ range .Links }}
<tr> <tr>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -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)
}
}
}

View File

@@ -302,18 +302,6 @@ func (h *Http) getIndex(body *schema.Index) *schema.Index {
return body.Clients[i].Name < body.Clients[j].Name return body.Clients[i].Name < body.Clients[j].Name
}) })
} }
// display esp state
for s := range cache.EspState.List("") {
if s == nil {
break
}
body.States = append(body.States, models.NewEspStateSchema(s))
}
sort.SliceStable(body.States, func(i, j int) bool {
ii := body.States[i]
jj := body.States[j]
return ii.Spi > jj.Spi
})
// display esp state // display esp state
for s := range cache.Output.List("") { for s := range cache.Output.List("") {

View File

@@ -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)
}
}
}

View File

@@ -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)
}

View File

@@ -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()
}

View File

@@ -19,12 +19,8 @@ import (
func NewNetworker(c *co.Network) api.Networker { func NewNetworker(c *co.Network) api.Networker {
var obj api.Networker var obj api.Networker
switch c.Provider { switch c.Provider {
case "esp":
obj = NewESPWorker(c)
case "vxlan": case "vxlan":
obj = NewVxLANWorker(c) obj = NewVxLANWorker(c)
case "fabric":
obj = NewFabricWorker(c)
case "router": case "router":
obj = NewRouterWorker(c) obj = NewRouterWorker(c)
default: default:

View File

@@ -3,8 +3,6 @@ package cswitch
import ( import (
"encoding/json" "encoding/json"
"os" "os"
"os/exec"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -102,8 +100,6 @@ type Switch struct {
uuid string uuid string
newTime int64 newTime int64
out *libol.SubLogger out *libol.SubLogger
confd *ConfD
l2tp *L2TP
} }
func NewSwitch(c *co.Switch) *Switch { func NewSwitch(c *co.Switch) *Switch {
@@ -117,7 +113,6 @@ func NewSwitch(c *co.Switch) *Switch {
hooks: make([]Hook, 0, 64), hooks: make([]Hook, 0, 64),
out: libol.NewSubLogger(c.Alias), out: libol.NewSubLogger(c.Alias),
} }
v.confd = NewConfd(v)
return v return v
} }
@@ -215,8 +210,8 @@ func (v *Switch) GetPort(listen string) string {
func (v *Switch) openPorts() { func (v *Switch) openPorts() {
port := v.GetPort(v.cfg.Listen) port := v.GetPort(v.cfg.Listen)
UdpPorts := []string{"4500", "4500", "8472", "4789", port} UdpPorts := []string{"500", "4500", "8472", "4789", port}
TcpPorts := []string{"7471", port} TcpPorts := []string{"10000", port}
if v.cfg.Http != nil { if v.cfg.Http != nil {
TcpPorts = append(TcpPorts, v.GetPort(v.cfg.Http.Listen)) TcpPorts = append(TcpPorts, v.GetPort(v.cfg.Http.Listen))
} }
@@ -287,12 +282,6 @@ func (v *Switch) Initialize() {
Crt: cert.CrtFile, Crt: cert.CrtFile,
}) })
} }
// Enable L2TP
if v.cfg.L2TP != nil {
v.l2tp = NewL2TP(v.cfg.L2TP)
}
// Start confd monitor
v.confd.Initialize()
} }
func (v *Switch) onFrame(client libol.SocketClient, frame *libol.FrameMessage) error { func (v *Switch) onFrame(client libol.SocketClient, frame *libol.FrameMessage) error {
@@ -394,18 +383,6 @@ func (v *Switch) OnClose(client libol.SocketClient) error {
return nil return nil
} }
func (v *Switch) openUdp() {
args := []string{
"-port", strconv.Itoa(co.EspLocalUdp),
"-log:file", "/var/openlan/openudp.log",
}
libol.Info("%s %v", UDPBin, args)
cmd := exec.Command(UDPBin, args...)
if err := cmd.Run(); err != nil {
libol.Error("Switch.OpenUdp %s", err)
}
}
func (v *Switch) Start() { func (v *Switch) Start() {
v.lock.Lock() v.lock.Lock()
defer v.lock.Unlock() defer v.lock.Unlock()
@@ -429,11 +406,6 @@ func (v *Switch) Start() {
if v.http != nil { if v.http != nil {
libol.Go(v.http.Start) libol.Go(v.http.Start)
} }
libol.Go(v.confd.Start)
if v.l2tp != nil {
libol.Go(v.l2tp.Start)
}
libol.Go(v.openUdp)
} }
func (v *Switch) Stop() { func (v *Switch) Stop() {
@@ -442,10 +414,6 @@ func (v *Switch) Stop() {
v.out.Info("Switch.Stop") v.out.Info("Switch.Stop")
if v.l2tp != nil {
v.l2tp.Stop()
}
v.confd.Stop()
if v.http != nil { if v.http != nil {
v.http.Shutdown() v.http.Shutdown()
} }