mirror of
https://github.com/fumiama/WireGold.git
synced 2025-09-26 19:21:11 +08:00
166 lines
3.9 KiB
Go
166 lines
3.9 KiB
Go
package wg
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"strconv"
|
|
|
|
base14 "github.com/fumiama/go-base16384"
|
|
curve "github.com/fumiama/go-x25519"
|
|
"github.com/sirupsen/logrus"
|
|
|
|
_ "github.com/fumiama/WireGold/gold/p2p/ip" // support ip connection
|
|
_ "github.com/fumiama/WireGold/gold/p2p/tcp" // support tcp connection
|
|
_ "github.com/fumiama/WireGold/gold/p2p/udp" // support udp connection
|
|
_ "github.com/fumiama/WireGold/gold/p2p/udplite" // support udplite connection
|
|
_ "github.com/fumiama/WireGold/gold/proto" // support basic protos
|
|
|
|
"github.com/fumiama/WireGold/config"
|
|
"github.com/fumiama/WireGold/gold/link"
|
|
"github.com/fumiama/WireGold/internal/bin"
|
|
)
|
|
|
|
const suffix32 = "㴄"
|
|
|
|
type WG struct {
|
|
c *config.Config
|
|
key [32]byte
|
|
PublicKey string
|
|
me link.Me
|
|
}
|
|
|
|
func NewWireGold(c *config.Config) (wg WG, err error) {
|
|
wg.c = c
|
|
|
|
var k []byte
|
|
k, err = base14.UTF82UTF16BE(bin.StringToBytes(c.PrivateKey + suffix32))
|
|
if err != nil {
|
|
return
|
|
}
|
|
n := copy(wg.key[:], base14.Decode(k))
|
|
if n != 32 {
|
|
err = errors.New("private key length != 32, got " + strconv.Itoa(n))
|
|
return
|
|
}
|
|
|
|
cur := curve.Get(wg.key[:])
|
|
pubk, err := base14.UTF16BE2UTF8(base14.Encode((*cur.Public())[:]))
|
|
if err != nil {
|
|
return
|
|
}
|
|
wg.PublicKey = bin.BytesToString(pubk[:57])
|
|
|
|
return
|
|
}
|
|
|
|
func (wg *WG) Start(srcport, destport uint16) {
|
|
go wg.Run(srcport, destport)
|
|
}
|
|
|
|
func (wg *WG) Run(srcport, destport uint16) {
|
|
wg.init(srcport, destport)
|
|
_, _ = wg.me.ListenNIC()
|
|
logrus.Infoln("[wg] stopped")
|
|
}
|
|
|
|
func (wg *WG) Stop() {
|
|
logrus.Warnln("[wg] stopping...")
|
|
_ = wg.me.Close()
|
|
}
|
|
|
|
func (wg *WG) init(srcport, dstport uint16) {
|
|
cidrsmap := make(map[string]bool, 32)
|
|
_, mysubnet, err := net.ParseCIDR(wg.c.SubNet)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
myip := net.ParseIP(wg.c.IP)
|
|
if myip == nil {
|
|
panic("invalid ip " + wg.c.IP)
|
|
}
|
|
for _, p := range wg.c.Peers {
|
|
for _, ip := range p.AllowedIPs {
|
|
if len(ip) == 0 || ip[0] == 'x' || ip[0] == 'y' {
|
|
continue
|
|
}
|
|
ipnet, _, err := net.ParseCIDR(ip)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if !mysubnet.Contains(ipnet) {
|
|
cidrsmap[ip] = true
|
|
}
|
|
}
|
|
}
|
|
cidrs := make([]string, len(cidrsmap))
|
|
i := 0
|
|
for k := range cidrsmap {
|
|
cidrs[i] = k
|
|
i++
|
|
}
|
|
|
|
wg.me = link.NewMe(&link.MyConfig{
|
|
MyIPwithMask: myip.String() + "/32",
|
|
MyEndpoint: wg.c.EndPoint,
|
|
Network: wg.c.Network,
|
|
PrivateKey: &wg.key,
|
|
NICConfig: &link.NICConfig{
|
|
IP: myip,
|
|
SubNet: mysubnet,
|
|
CIDRs: cidrs,
|
|
},
|
|
SrcPort: srcport,
|
|
DstPort: dstport,
|
|
MTU: uint16(wg.c.MTU),
|
|
SpeedLoop: wg.c.SpeedLoop,
|
|
Mask: wg.c.Mask,
|
|
Base14: wg.c.Base14,
|
|
})
|
|
|
|
for _, peer := range wg.c.Peers {
|
|
var peerkey [32]byte
|
|
k, err := base14.UTF82UTF16BE(bin.StringToBytes(peer.PublicKey + suffix32))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
n := copy(peerkey[:], base14.Decode(k))
|
|
if n != 32 {
|
|
panic("peer " + peer.IP + ": public key length < 32")
|
|
}
|
|
var pshk *[32]byte
|
|
if peer.PresharedKey != "" {
|
|
k, err := base14.UTF82UTF16BE(bin.StringToBytes(peer.PresharedKey + suffix32))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
pshk = &[32]byte{}
|
|
n := copy(pshk[:], base14.Decode(k))
|
|
if n != 32 {
|
|
panic("peer " + peer.IP + ": preshared key length < 32")
|
|
}
|
|
}
|
|
if peer.MTU >= 65535 {
|
|
panic("peer " + peer.IP + ": MTU too large")
|
|
}
|
|
if peer.MTURandomRange >= peer.MTU/2 {
|
|
panic("peer " + peer.IP + ": MTURandomRange too large")
|
|
}
|
|
wg.me.AddPeer(&link.PeerConfig{
|
|
PeerIP: peer.IP,
|
|
EndPoint: peer.EndPoint,
|
|
AllowedIPs: peer.AllowedIPs,
|
|
Querys: peer.QueryList,
|
|
PubicKey: &peerkey,
|
|
PresharedKey: pshk,
|
|
KeepAliveDur: peer.KeepAliveSeconds,
|
|
QueryTick: peer.QuerySeconds,
|
|
MTU: uint16(peer.MTU),
|
|
MTURandomRange: uint16(peer.MTURandomRange),
|
|
AllowTrans: peer.AllowTrans,
|
|
NoPipe: true,
|
|
UseZstd: peer.UseZstd,
|
|
DoublePacket: peer.DoublePacket,
|
|
})
|
|
}
|
|
}
|