mirror of
https://github.com/luscis/openlan.git
synced 2025-10-05 16:47:11 +08:00
267 lines
5.2 KiB
Go
Executable File
267 lines
5.2 KiB
Go
Executable File
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
|
|
}
|