mirror of
https://github.com/fumiama/WireGold.git
synced 2026-07-02 08:30:25 +08:00
feat: add preshared key
This commit is contained in:
@@ -42,6 +42,7 @@ Peers:
|
|||||||
IP: "192.168.233.2"
|
IP: "192.168.233.2"
|
||||||
SubNet: 192.168.233.0/24
|
SubNet: 192.168.233.0/24
|
||||||
PublicKey: 徯萃嵾爻燸攗窍褃冔蒔犡緇袿屿組待族砇嘀
|
PublicKey: 徯萃嵾爻燸攗窍褃冔蒔犡緇袿屿組待族砇嘀
|
||||||
|
PresharedKey: 瀸敀爅崾嘊嵜紼樴稍毯攣矐訷蟷扛嬋庩崛昀
|
||||||
EndPoint: 1.2.3.4:56789
|
EndPoint: 1.2.3.4:56789
|
||||||
AllowedIPs: ["192.168.233.2/32"]
|
AllowedIPs: ["192.168.233.2/32"]
|
||||||
KeepAliveSeconds: 0
|
KeepAliveSeconds: 0
|
||||||
@@ -53,6 +54,7 @@ Peers:
|
|||||||
IP: "192.168.233.3"
|
IP: "192.168.233.3"
|
||||||
SubNet: 192.168.233.0/24
|
SubNet: 192.168.233.0/24
|
||||||
PublicKey: 牢喨粷詸衭譛浾蘹櫠砙杹蟫瑳叩刋橋経挵蘀
|
PublicKey: 牢喨粷詸衭譛浾蘹櫠砙杹蟫瑳叩刋橋経挵蘀
|
||||||
|
PresharedKey: 竅琚喫従痸告烈兇厕趭萨假蔛瀇譄施烸蝫瘀
|
||||||
EndPoint: ""
|
EndPoint: ""
|
||||||
AllowedIPs: ["192.168.233.3/32"]
|
AllowedIPs: ["192.168.233.3/32"]
|
||||||
MTU: 752
|
MTU: 752
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type Peer struct {
|
|||||||
IP string `yaml:"IP"`
|
IP string `yaml:"IP"`
|
||||||
SubNet string `yaml:"SubNet"`
|
SubNet string `yaml:"SubNet"`
|
||||||
PublicKey string `yaml:"PublicKey"`
|
PublicKey string `yaml:"PublicKey"`
|
||||||
|
PresharedKey string `yaml:"PresharedKey"`
|
||||||
EndPoint string `yaml:"EndPoint"`
|
EndPoint string `yaml:"EndPoint"`
|
||||||
AllowedIPs []string `yaml:"AllowedIPs"`
|
AllowedIPs []string `yaml:"AllowedIPs"`
|
||||||
KeepAliveSeconds int64 `yaml:"KeepAliveSeconds"`
|
KeepAliveSeconds int64 `yaml:"KeepAliveSeconds"`
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"hash/crc64"
|
"hash/crc64"
|
||||||
"net"
|
"net"
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/WireGold/helper"
|
||||||
blake2b "github.com/fumiama/blake2b-simd"
|
blake2b "github.com/fumiama/blake2b-simd"
|
||||||
@@ -17,7 +16,7 @@ import (
|
|||||||
type Packet struct {
|
type Packet struct {
|
||||||
// TeaTypeDataSZ len(Data)
|
// TeaTypeDataSZ len(Data)
|
||||||
// 高 4 位指定加密所用 tea key
|
// 高 4 位指定加密所用 tea key
|
||||||
// 高 4-16 位是随机值
|
// 高 4-16 位是递增值, 用于预共享密钥验证 additionalData
|
||||||
// 不得超过 65507-head 字节
|
// 不得超过 65507-head 字节
|
||||||
TeaTypeDataSZ uint32
|
TeaTypeDataSZ uint32
|
||||||
// Proto 详见 head
|
// Proto 详见 head
|
||||||
@@ -109,18 +108,16 @@ func (p *Packet) Unmarshal(data []byte) (complete bool, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var counter uint32
|
|
||||||
|
|
||||||
// Marshal 将自身数据编码为 []byte
|
// Marshal 将自身数据编码为 []byte
|
||||||
// offset 必须为 8 的倍数,表示偏移的 8 位
|
// offset 必须为 8 的倍数,表示偏移的 8 位
|
||||||
func (p *Packet) Marshal(src net.IP, teatype uint8, datasz uint32, offset uint16, dontfrag, hasmore bool) ([]byte, func()) {
|
func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz uint32, offset uint16, dontfrag, hasmore bool) ([]byte, func()) {
|
||||||
p.TTL--
|
p.TTL--
|
||||||
if p.TTL == 0 {
|
if p.TTL == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if src != nil {
|
if src != nil {
|
||||||
p.TeaTypeDataSZ = uint32(teatype)<<28 | (atomic.AddUint32(&counter, 1)<<16)&0x0fff0000 | datasz
|
p.TeaTypeDataSZ = uint32(teatype)<<28 | (uint32(additional&0x0fff) << 16) | datasz&0xffff
|
||||||
p.Src = src
|
p.Src = src
|
||||||
offset &= 0x1fff
|
offset &= 0x1fff
|
||||||
if dontfrag {
|
if dontfrag {
|
||||||
@@ -171,6 +168,11 @@ func (p *Packet) IsVaildHash() bool {
|
|||||||
return sum == p.Hash
|
return sum == p.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdditionalData 获得 packet 的 additionalData
|
||||||
|
func (p *Packet) AdditionalData() uint16 {
|
||||||
|
return uint16((p.TeaTypeDataSZ >> 16) & 0x0fff)
|
||||||
|
}
|
||||||
|
|
||||||
// Put 将自己放回池中
|
// Put 将自己放回池中
|
||||||
func (p *Packet) Put() {
|
func (p *Packet) Put() {
|
||||||
PutPacket(p)
|
PutPacket(p)
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package link
|
package link
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
// Encode 使用 TEA 加密
|
// Encode 使用 TEA 加密
|
||||||
func (l *Link) Encode(teatype uint8, b []byte) (eb []byte) {
|
func (l *Link) Encode(teatype uint8, b []byte) (eb []byte) {
|
||||||
if b == nil || teatype >= 16 {
|
if b == nil || teatype >= 16 {
|
||||||
@@ -29,3 +34,34 @@ func (l *Link) Decode(teatype uint8, b []byte) (db []byte) {
|
|||||||
db = l.key[teatype].Decrypt(b)
|
db = l.key[teatype].Decrypt(b)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EncodePreshared 使用 chacha20poly1305 加密
|
||||||
|
func (l *Link) EncodePreshared(additional uint16, b []byte) (eb []byte) {
|
||||||
|
nsz := l.aead.NonceSize()
|
||||||
|
// Select a random nonce, and leave capacity for the ciphertext.
|
||||||
|
nonce := make([]byte, nsz, nsz+len(b)+l.aead.Overhead())
|
||||||
|
_, err := rand.Read(nonce)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Encrypt the message and append the ciphertext to the nonce.
|
||||||
|
var buf [2]byte
|
||||||
|
binary.LittleEndian.PutUint16(buf[:], additional)
|
||||||
|
eb = l.aead.Seal(nonce, nonce, b, buf[:])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodePreshared 使用 chacha20poly1305 解密
|
||||||
|
func (l *Link) DecodePreshared(additional uint16, b []byte) (db []byte) {
|
||||||
|
nsz := l.aead.NonceSize()
|
||||||
|
if len(b) < nsz { // ciphertext too short
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Split nonce and ciphertext.
|
||||||
|
nonce, ciphertext := b[:nsz], b[nsz:]
|
||||||
|
// Decrypt the message and check it wasn't tampered with.
|
||||||
|
var buf [2]byte
|
||||||
|
binary.LittleEndian.PutUint16(buf[:], additional)
|
||||||
|
db, _ = l.aead.Open(nil, nonce, ciphertext, buf[:])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package link
|
package link
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
@@ -14,6 +15,8 @@ import (
|
|||||||
type Link struct {
|
type Link struct {
|
||||||
// peer 的公钥
|
// peer 的公钥
|
||||||
pubk *[32]byte
|
pubk *[32]byte
|
||||||
|
// 发包计数, 分片算一个
|
||||||
|
sendcount uintptr
|
||||||
// 收到的包的队列
|
// 收到的包的队列
|
||||||
// 没有下层 nic 时
|
// 没有下层 nic 时
|
||||||
// 包会分发到此
|
// 包会分发到此
|
||||||
@@ -26,6 +29,8 @@ type Link struct {
|
|||||||
allowedips []*net.IPNet
|
allowedips []*net.IPNet
|
||||||
// 连接所用对称加密密钥
|
// 连接所用对称加密密钥
|
||||||
key []tea.TEA
|
key []tea.TEA
|
||||||
|
// 连接所用预共享密钥
|
||||||
|
aead cipher.AEAD
|
||||||
// 本机信息
|
// 本机信息
|
||||||
me *Me
|
me *Me
|
||||||
// 连接的状态,详见下方 const
|
// 连接的状态,详见下方 const
|
||||||
|
|||||||
@@ -43,40 +43,48 @@ func (m *Me) listenthread(conn *net.UDPConn, mu *sync.Mutex) {
|
|||||||
sz := packet.TeaTypeDataSZ & 0x0000ffff
|
sz := packet.TeaTypeDataSZ & 0x0000ffff
|
||||||
r := int(sz) - len(packet.Data)
|
r := int(sz) - len(packet.Data)
|
||||||
if r > 0 {
|
if r > 0 {
|
||||||
logrus.Warnln("[link] packet from endpoint", addr, "is smaller than it declared: drop it")
|
logrus.Warnln("[listen] packet from endpoint", addr, "is smaller than it declared: drop it")
|
||||||
packet.Put()
|
packet.Put()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p, ok := m.IsInPeer(packet.Src.String())
|
p, ok := m.IsInPeer(packet.Src.String())
|
||||||
logrus.Debugln("[link] recv from endpoint", addr, "src", packet.Src, "dst", packet.Dst)
|
logrus.Debugln("[listen] recv from endpoint", addr, "src", packet.Src, "dst", packet.Dst)
|
||||||
// logrus.Debugln("[link] recv:", hex.EncodeToString(lbf))
|
// logrus.Debugln("[listen] recv:", hex.EncodeToString(lbf))
|
||||||
if !ok {
|
if !ok {
|
||||||
logrus.Warnln("[link] packet from", packet.Src, "to", packet.Dst, "is refused")
|
logrus.Warnln("[listen] packet from", packet.Src, "to", packet.Dst, "is refused")
|
||||||
packet.Put()
|
packet.Put()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if p.endpoint == nil || p.endpoint.String() != addr.String() {
|
if p.endpoint == nil || p.endpoint.String() != addr.String() {
|
||||||
logrus.Infoln("[link] set endpoint of peer", p.peerip, "to", addr.String())
|
logrus.Infoln("[listen] set endpoint of peer", p.peerip, "to", addr.String())
|
||||||
p.endpoint = addr
|
p.endpoint = addr
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case p.IsToMe(packet.Dst):
|
case p.IsToMe(packet.Dst):
|
||||||
packet.Data = p.Decode(uint8(packet.TeaTypeDataSZ>>28), packet.Data)
|
packet.Data = p.Decode(uint8(packet.TeaTypeDataSZ>>28), packet.Data)
|
||||||
if !packet.IsVaildHash() {
|
if !packet.IsVaildHash() {
|
||||||
logrus.Debugln("[link] drop invalid packet")
|
logrus.Debugln("[listen] drop invalid hash packet")
|
||||||
packet.Put()
|
packet.Put()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if p.aead != nil {
|
||||||
|
packet.Data = p.DecodePreshared(packet.AdditionalData(), packet.Data)
|
||||||
|
if packet.Data == nil {
|
||||||
|
logrus.Debugln("[listen] drop invalid additional data packet")
|
||||||
|
packet.Put()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
switch packet.Proto {
|
switch packet.Proto {
|
||||||
case head.ProtoHello:
|
case head.ProtoHello:
|
||||||
switch p.status {
|
switch p.status {
|
||||||
case LINK_STATUS_DOWN:
|
case LINK_STATUS_DOWN:
|
||||||
n, err = p.WriteAndPut(head.NewPacket(head.ProtoHello, m.SrcPort(), p.peerip, m.DstPort(), nil), false)
|
n, err = p.WriteAndPut(head.NewPacket(head.ProtoHello, m.SrcPort(), p.peerip, m.DstPort(), nil), false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Debugln("[link] send", n, "bytes hello ack packet")
|
logrus.Debugln("[listen] send", n, "bytes hello ack packet")
|
||||||
p.status = LINK_STATUS_HALFUP
|
p.status = LINK_STATUS_HALFUP
|
||||||
} else {
|
} else {
|
||||||
logrus.Errorln("[link] send hello ack packet error:", err)
|
logrus.Errorln("[listen] send hello ack packet error:", err)
|
||||||
}
|
}
|
||||||
case LINK_STATUS_HALFUP:
|
case LINK_STATUS_HALFUP:
|
||||||
p.status = LINK_STATUS_UP
|
p.status = LINK_STATUS_UP
|
||||||
@@ -84,47 +92,47 @@ func (m *Me) listenthread(conn *net.UDPConn, mu *sync.Mutex) {
|
|||||||
}
|
}
|
||||||
packet.Put()
|
packet.Put()
|
||||||
case head.ProtoNotify:
|
case head.ProtoNotify:
|
||||||
logrus.Infoln("[link] recv notify from", packet.Src)
|
logrus.Infoln("[listen] recv notify from", packet.Src)
|
||||||
go p.onNotify(packet.Data)
|
go p.onNotify(packet.Data)
|
||||||
packet.Put()
|
packet.Put()
|
||||||
case head.ProtoQuery:
|
case head.ProtoQuery:
|
||||||
logrus.Infoln("[link] recv query from", packet.Src)
|
logrus.Infoln("[listen] recv query from", packet.Src)
|
||||||
go p.onQuery(packet.Data)
|
go p.onQuery(packet.Data)
|
||||||
packet.Put()
|
packet.Put()
|
||||||
case head.ProtoData:
|
case head.ProtoData:
|
||||||
if p.pipe != nil {
|
if p.pipe != nil {
|
||||||
p.pipe <- packet
|
p.pipe <- packet
|
||||||
logrus.Debugln("[link] deliver to pipe of", p.peerip)
|
logrus.Debugln("[listen] deliver to pipe of", p.peerip)
|
||||||
} else {
|
} else {
|
||||||
m.nic.Write(packet.Data)
|
m.nic.Write(packet.Data)
|
||||||
logrus.Debugln("[link] deliver", len(packet.Data), "bytes data to nic")
|
logrus.Debugln("[listen] deliver", len(packet.Data), "bytes data to nic")
|
||||||
packet.Put()
|
packet.Put()
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
logrus.Warnln("[link] recv unknown proto:", packet.Proto)
|
logrus.Warnln("[listen] recv unknown proto:", packet.Proto)
|
||||||
packet.Put()
|
packet.Put()
|
||||||
}
|
}
|
||||||
case p.Accept(packet.Dst):
|
case p.Accept(packet.Dst):
|
||||||
if !p.allowtrans {
|
if !p.allowtrans {
|
||||||
logrus.Warnln("[link] refused to trans packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)))
|
logrus.Warnln("[listen] refused to trans packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)))
|
||||||
packet.Put()
|
packet.Put()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 转发
|
// 转发
|
||||||
lnk := m.router.NextHop(packet.Dst.String())
|
lnk := m.router.NextHop(packet.Dst.String())
|
||||||
if lnk == nil {
|
if lnk == nil {
|
||||||
logrus.Warnln("[link] transfer drop packet: nil nexthop")
|
logrus.Warnln("[listen] transfer drop packet: nil nexthop")
|
||||||
packet.Put()
|
packet.Put()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
n, err = lnk.WriteAndPut(packet, true)
|
n, err = lnk.WriteAndPut(packet, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Debugln("[link] trans", n, "bytes packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)))
|
logrus.Debugln("[listen] trans", n, "bytes packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)))
|
||||||
} else {
|
} else {
|
||||||
logrus.Errorln("[link] trans packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)), "err:", err)
|
logrus.Errorln("[listen] trans packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)), "err:", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
logrus.Warnln("[link] packet dst", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)), "is not in peers")
|
logrus.Warnln("[listen] packet dst", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)), "is not in peers")
|
||||||
packet.Put()
|
packet.Put()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ import (
|
|||||||
// 以秒为单位,小于等于 0 不发送
|
// 以秒为单位,小于等于 0 不发送
|
||||||
func (l *Link) keepAlive(dur int64) {
|
func (l *Link) keepAlive(dur int64) {
|
||||||
if dur > 0 {
|
if dur > 0 {
|
||||||
logrus.Infoln("[link.nat] start to keep alive")
|
logrus.Infoln("[nat] start to keep alive")
|
||||||
t := time.NewTicker(time.Second * time.Duration(dur))
|
t := time.NewTicker(time.Second * time.Duration(dur))
|
||||||
for range t.C {
|
for range t.C {
|
||||||
n, err := l.WriteAndPut(head.NewPacket(head.ProtoHello, l.me.srcport, l.peerip, l.me.dstport, nil), false)
|
n, err := l.WriteAndPut(head.NewPacket(head.ProtoHello, l.me.srcport, l.peerip, l.me.dstport, nil), false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Infoln("[link] send", n, "bytes keep alive packet")
|
logrus.Infoln("[nat] send", n, "bytes keep alive packet")
|
||||||
} else {
|
} else {
|
||||||
logrus.Errorln("[link] send keep alive packet error:", err)
|
logrus.Errorln("[nat] send keep alive packet error:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ func (l *Link) onNotify(packet []byte) {
|
|||||||
notify := make(head.Notify, 32)
|
notify := make(head.Notify, 32)
|
||||||
err := json.Unmarshal(packet, ¬ify)
|
err := json.Unmarshal(packet, ¬ify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[notify] json unmarshal err:", err)
|
logrus.Errorln("[nat] notify json unmarshal err:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 2. endpoint注册
|
// 2. endpoint注册
|
||||||
@@ -50,12 +50,12 @@ func (l *Link) onNotify(packet []byte) {
|
|||||||
if ok {
|
if ok {
|
||||||
if p.endpoint.String() != ep {
|
if p.endpoint.String() != ep {
|
||||||
p.endpoint = addr
|
p.endpoint = addr
|
||||||
logrus.Infoln("[notify] set ep of peer", peer, "to", ep)
|
logrus.Infoln("[nat] notify set ep of peer", peer, "to", ep)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logrus.Debugln("[notify] drop invalid peer:", peer, "ep:", ep)
|
logrus.Debugln("[nat] notify drop invalid peer:", peer, "ep:", ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ func (l *Link) onQuery(packet []byte) {
|
|||||||
var peers head.Query
|
var peers head.Query
|
||||||
err := json.Unmarshal(packet, &peers)
|
err := json.Unmarshal(packet, &peers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[qurey] json unmarshal err:", err)
|
logrus.Errorln("[nat] query json unmarshal err:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ func (l *Link) onQuery(packet []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(notify) > 0 {
|
if len(notify) > 0 {
|
||||||
logrus.Infoln("[query] wrap", len(notify), "notify")
|
logrus.Infoln("[nat] query wrap", len(notify), "notify")
|
||||||
w := helper.SelectWriter()
|
w := helper.SelectWriter()
|
||||||
json.NewEncoder(w).Encode(¬ify)
|
json.NewEncoder(w).Encode(¬ify)
|
||||||
l.WriteAndPut(head.NewPacket(head.ProtoNotify, l.me.srcport, l.peerip, l.me.dstport, w.Bytes()), false)
|
l.WriteAndPut(head.NewPacket(head.ProtoNotify, l.me.srcport, l.peerip, l.me.dstport, w.Bytes()), false)
|
||||||
@@ -103,10 +103,10 @@ func (l *Link) sendquery(tick time.Duration, peers ...string) {
|
|||||||
}
|
}
|
||||||
t := time.NewTicker(tick)
|
t := time.NewTicker(tick)
|
||||||
for range t.C {
|
for range t.C {
|
||||||
logrus.Infoln("[query] send query to", l.peerip)
|
logrus.Infoln("[nat] query send query to", l.peerip)
|
||||||
_, err = l.WriteAndPut(head.NewPacket(head.ProtoQuery, l.me.srcport, l.peerip, l.me.dstport, data), false)
|
_, err = l.WriteAndPut(head.NewPacket(head.ProtoQuery, l.me.srcport, l.peerip, l.me.dstport, data), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[query] write err:", err)
|
logrus.Errorln("[nat] query write err:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
curve "github.com/fumiama/go-x25519"
|
curve "github.com/fumiama/go-x25519"
|
||||||
tea "github.com/fumiama/gofastTEA"
|
tea "github.com/fumiama/gofastTEA"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PeerConfig struct {
|
type PeerConfig struct {
|
||||||
@@ -15,6 +16,7 @@ type PeerConfig struct {
|
|||||||
EndPoint string
|
EndPoint string
|
||||||
AllowedIPs, Querys []string
|
AllowedIPs, Querys []string
|
||||||
PubicKey *[32]byte
|
PubicKey *[32]byte
|
||||||
|
PresharedKey *[32]byte
|
||||||
KeepAliveDur, QueryTick int64
|
KeepAliveDur, QueryTick int64
|
||||||
MTU uint16
|
MTU uint16
|
||||||
AllowTrans, NoPipe bool
|
AllowTrans, NoPipe bool
|
||||||
@@ -52,6 +54,13 @@ func (m *Me) AddPeer(cfg *PeerConfig) (l *Link) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if cfg.PresharedKey != nil {
|
||||||
|
var err error
|
||||||
|
l.aead, err = chacha20poly1305.NewX(cfg.PresharedKey[:])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if cfg.EndPoint != "" {
|
if cfg.EndPoint != "" {
|
||||||
e, err := net.ResolveUDPAddr("udp", cfg.EndPoint)
|
e, err := net.ResolveUDPAddr("udp", cfg.EndPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -12,16 +13,23 @@ import (
|
|||||||
// WriteAndPut 向 peer 发包并将包放回缓存池
|
// WriteAndPut 向 peer 发包并将包放回缓存池
|
||||||
func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
|
func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
|
||||||
teatype := uint8(rand.Intn(16))
|
teatype := uint8(rand.Intn(16))
|
||||||
|
sndcnt := atomic.AddUintptr(&l.sendcount, 1)
|
||||||
if len(p.Data) <= int(l.mtu) {
|
if len(p.Data) <= int(l.mtu) {
|
||||||
if !istransfer {
|
if !istransfer {
|
||||||
p.FillHash()
|
p.FillHash()
|
||||||
|
if l.aead != nil {
|
||||||
|
p.Data = l.EncodePreshared(uint16(sndcnt), p.Data)
|
||||||
|
}
|
||||||
p.Data = l.Encode(teatype, p.Data)
|
p.Data = l.Encode(teatype, p.Data)
|
||||||
}
|
}
|
||||||
defer p.Put()
|
defer p.Put()
|
||||||
return l.write(p, teatype, uint32(len(p.Data)), 0, istransfer, false)
|
return l.write(p, teatype, uint16(sndcnt), uint32(len(p.Data)), 0, istransfer, false)
|
||||||
}
|
}
|
||||||
if !istransfer {
|
if !istransfer {
|
||||||
p.FillHash()
|
p.FillHash()
|
||||||
|
if l.aead != nil {
|
||||||
|
p.Data = l.EncodePreshared(uint16(sndcnt), p.Data)
|
||||||
|
}
|
||||||
p.Data = l.Encode(teatype, p.Data)
|
p.Data = l.Encode(teatype, p.Data)
|
||||||
}
|
}
|
||||||
data := p.Data
|
data := p.Data
|
||||||
@@ -31,9 +39,9 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
|
|||||||
packet := head.SelectPacket()
|
packet := head.SelectPacket()
|
||||||
*packet = *p
|
*packet = *p
|
||||||
for ; int(totl)-i > int(l.mtu); i += int(l.mtu) {
|
for ; int(totl)-i > int(l.mtu); i += int(l.mtu) {
|
||||||
logrus.Debugln("[link] split frag", i, ":", i+int(l.mtu), ", remain:", int(totl)-i-int(l.mtu))
|
logrus.Debugln("[send] split frag", i, ":", i+int(l.mtu), ", remain:", int(totl)-i-int(l.mtu))
|
||||||
packet.Data = data[:int(l.mtu)]
|
packet.Data = data[:int(l.mtu)]
|
||||||
cnt, err := l.write(packet, teatype, totl, uint16(i>>3), istransfer, true)
|
cnt, err := l.write(packet, teatype, uint16(sndcnt), totl, uint16(i>>3), istransfer, true)
|
||||||
n += cnt
|
n += cnt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
@@ -43,33 +51,33 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
|
|||||||
}
|
}
|
||||||
packet.Put()
|
packet.Put()
|
||||||
p.Data = data
|
p.Data = data
|
||||||
cnt, err := l.write(p, teatype, totl, uint16(i>>3), istransfer, false)
|
cnt, err := l.write(p, teatype, uint16(sndcnt), totl, uint16(i>>3), istransfer, false)
|
||||||
p.Put()
|
p.Put()
|
||||||
n += cnt
|
n += cnt
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// write 向 peer 发一个包
|
// write 向 peer 发一个包
|
||||||
func (l *Link) write(p *head.Packet, teatype uint8, datasz uint32, offset uint16, istransfer, hasmore bool) (n int, err error) {
|
func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool) (n int, err error) {
|
||||||
var d []byte
|
var d []byte
|
||||||
var cl func()
|
var cl func()
|
||||||
if istransfer {
|
if istransfer {
|
||||||
if p.Flags&0x4000 == 0x4000 && len(p.Data) > int(l.mtu) {
|
if p.Flags&0x4000 == 0x4000 && len(p.Data) > int(l.mtu) {
|
||||||
return len(p.Data), errors.New("drop dont fragmnet big trans packet")
|
return len(p.Data), errors.New("drop dont fragmnet big trans packet")
|
||||||
}
|
}
|
||||||
d, cl = p.Marshal(nil, teatype, 0, 0, false, false)
|
d, cl = p.Marshal(nil, teatype, additional, 0, 0, false, false)
|
||||||
} else {
|
} else {
|
||||||
d, cl = p.Marshal(l.me.me, teatype, datasz, offset, false, hasmore)
|
d, cl = p.Marshal(l.me.me, teatype, additional, datasz, offset, false, hasmore)
|
||||||
}
|
}
|
||||||
if d == nil {
|
if d == nil {
|
||||||
return 0, errors.New("[link] ttl exceeded")
|
return 0, errors.New("[send] ttl exceeded")
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
peerep := l.endpoint
|
peerep := l.endpoint
|
||||||
if peerep == nil {
|
if peerep == nil {
|
||||||
return 0, errors.New("[link] nil endpoint of " + p.Dst.String())
|
return 0, errors.New("[send] nil endpoint of " + p.Dst.String())
|
||||||
}
|
}
|
||||||
logrus.Debugln("[link] write", len(d), "bytes data from ep", l.me.myep.LocalAddr(), "to", peerep, "offset:", fmt.Sprintf("%04x", offset))
|
logrus.Debugln("[send] write", len(d), "bytes data from ep", l.me.myep.LocalAddr(), "to", peerep, "offset:", fmt.Sprintf("%04x", offset))
|
||||||
n, err = l.me.myep.WriteToUDP(d, peerep)
|
n, err = l.me.myep.WriteToUDP(d, peerep)
|
||||||
cl()
|
cl()
|
||||||
}
|
}
|
||||||
|
|||||||
15
main.go
15
main.go
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -19,6 +20,7 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
help := flag.Bool("h", false, "display this help")
|
help := flag.Bool("h", false, "display this help")
|
||||||
gen := flag.Bool("g", false, "generate key pair")
|
gen := flag.Bool("g", false, "generate key pair")
|
||||||
|
pshgen := flag.Bool("pg", false, "generate preshared key")
|
||||||
showp := flag.Bool("p", false, "show my publickey")
|
showp := flag.Bool("p", false, "show my publickey")
|
||||||
file := flag.String("c", "config.yaml", "specify conf file")
|
file := flag.String("c", "config.yaml", "specify conf file")
|
||||||
debug := flag.Bool("d", false, "print debug logs")
|
debug := flag.Bool("d", false, "print debug logs")
|
||||||
@@ -50,6 +52,19 @@ func main() {
|
|||||||
fmt.Println("PrivateKey:", helper.BytesToString(prvk[:57]))
|
fmt.Println("PrivateKey:", helper.BytesToString(prvk[:57]))
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
if *pshgen {
|
||||||
|
var buf [32]byte
|
||||||
|
_, err := rand.Read(buf[:])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pshk, err := base14.UTF16BE2UTF8(base14.Encode(buf[:]))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println("PresharedKey:", helper.BytesToString(pshk[:57]))
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
if *logfile != "-" {
|
if *logfile != "-" {
|
||||||
f, err := os.Create(*logfile)
|
f, err := os.Create(*logfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -107,7 +107,19 @@ func (wg *WG) init(srcport, dstport uint16) {
|
|||||||
}
|
}
|
||||||
n := copy(peerkey[:], base14.Decode(k))
|
n := copy(peerkey[:], base14.Decode(k))
|
||||||
if n != 32 {
|
if n != 32 {
|
||||||
panic("peer public key length is not 32")
|
panic("peer public key length < 32")
|
||||||
|
}
|
||||||
|
var pshk *[32]byte
|
||||||
|
if peer.PresharedKey != "" {
|
||||||
|
k, err := base14.UTF82UTF16BE(helper.StringToBytes(peer.PresharedKey + suffix32))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pshk = &[32]byte{}
|
||||||
|
n := copy(pshk[:], base14.Decode(k))
|
||||||
|
if n != 32 {
|
||||||
|
panic("peer preshared key length < 32")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wg.me.AddPeer(&link.PeerConfig{
|
wg.me.AddPeer(&link.PeerConfig{
|
||||||
PeerIP: peer.IP,
|
PeerIP: peer.IP,
|
||||||
@@ -115,6 +127,7 @@ func (wg *WG) init(srcport, dstport uint16) {
|
|||||||
AllowedIPs: peer.AllowedIPs,
|
AllowedIPs: peer.AllowedIPs,
|
||||||
Querys: peer.QueryList,
|
Querys: peer.QueryList,
|
||||||
PubicKey: &peerkey,
|
PubicKey: &peerkey,
|
||||||
|
PresharedKey: pshk,
|
||||||
KeepAliveDur: peer.KeepAliveSeconds,
|
KeepAliveDur: peer.KeepAliveSeconds,
|
||||||
QueryTick: peer.QuerySeconds,
|
QueryTick: peer.QuerySeconds,
|
||||||
MTU: uint16(peer.MTU),
|
MTU: uint16(peer.MTU),
|
||||||
|
|||||||
Reference in New Issue
Block a user