mirror of
https://github.com/luscis/openlan.git
synced 2025-10-07 01:22:51 +08:00
257 lines
5.3 KiB
Go
Executable File
257 lines
5.3 KiB
Go
Executable File
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/luscis/openlan/pkg/libol"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
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" yaml:"local,omitempty"`
|
|
LocalIp net.IP `json:"local_addr" yaml:"local_addr"`
|
|
Remote string `json:"remote,omitempty" yaml:"remote,omitempty"`
|
|
RemotePort int `json:"remote_port" yaml:"remote_port"`
|
|
RemoteIp net.IP `json:"remote_addr" yaml:"remote_addr"`
|
|
Encap string `json:"encap,omitempty" yaml:"encapsulation,omitempty"`
|
|
Auth string `json:"auth,omitempty" yaml:"auth,omitempty"`
|
|
Crypt string `json:"crypt,omitempty" yaml:"crypt,omitempty"`
|
|
}
|
|
|
|
func (s *EspState) Padding(value string, size int) string {
|
|
return strings.Repeat(value, 64/len(value))[:size]
|
|
}
|
|
|
|
func (s *EspState) Correct(obj *EspState) {
|
|
if obj != nil {
|
|
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
|
|
}
|
|
}
|
|
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"`
|
|
}
|
|
|
|
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"`
|
|
Address string `json:"address,omitempty"`
|
|
Peer string `json:"peer"`
|
|
Spi int `json:"spi"`
|
|
State EspState `json:"state"`
|
|
Policies []*ESPPolicy `json:"policies" yaml:"policies,omitempty"`
|
|
}
|
|
|
|
func (m *ESPMember) Correct(state *EspState) {
|
|
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)
|
|
ptr := &m.State
|
|
ptr.Correct(state)
|
|
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" yaml:"state,omitempty"`
|
|
Members []*ESPMember `json:"members"`
|
|
Listen string `json:"listen,omitempty"`
|
|
}
|
|
|
|
func (n *ESPSpecifies) Correct() {
|
|
if n.Listen != "" {
|
|
addr, port := libol.GetHostPort(n.Listen)
|
|
if addr != "" {
|
|
n.State.Local = addr
|
|
}
|
|
if port != "" {
|
|
SetLocalUdp(port)
|
|
}
|
|
}
|
|
for _, m := range n.Members {
|
|
if m.Address == "" {
|
|
m.Address = n.Address
|
|
}
|
|
m.Correct(&n.State)
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|