1
0
mirror of https://github.com/fumiama/WireGold.git synced 2026-06-22 11:30:31 +08:00

完善注释

This commit is contained in:
fumiama
2021-10-25 19:29:59 +08:00
parent e29d5b2f48
commit fe6abd3898
10 changed files with 132 additions and 61 deletions

View File

@@ -1,7 +1,7 @@
package head package head
// map[peerip]endpoint // Notify 是 map[peerip]endpoint
type Notify map[string]string type Notify map[string]string
// peerips array // Query 是 peerips 组成的数组
type Query []string type Query []string

View File

@@ -2,17 +2,31 @@ package head
import "encoding/json" import "encoding/json"
// Packet 是发送和接收的最小单位
type Packet struct { type Packet struct {
DataSZ uint32 // DataSZ len(Data)
Proto uint8 DataSZ uint32
TTL uint8 // Proto 详见 head
Proto uint8
// TTL is time to live
TTL uint8
// SrcPort 源端口
SrcPort uint16 SrcPort uint16
// DstPort 目的端口
DstPort uint16 DstPort uint16
Src string // Src 源 ip
Dst string Src string
Data []byte // Dst 目的 ip
Dst string
// Hash 使用 BLAKE2 生成加密前 Packet 的摘要
// 生成时 Hash 全 0
// https://github.com/minio/blake2b-simd
Hash [32]byte
// Data 承载的数据
Data []byte
} }
// NewPacket 生成一个新包
func NewPacket(proto uint8, srcPort uint16, dstPort uint16, data []byte) *Packet { func NewPacket(proto uint8, srcPort uint16, dstPort uint16, data []byte) *Packet {
return &Packet{ return &Packet{
Proto: proto, Proto: proto,
@@ -23,10 +37,14 @@ func NewPacket(proto uint8, srcPort uint16, dstPort uint16, data []byte) *Packet
} }
} }
// UnMashal 将 data 的数据解码到自身
// 同时通过 Hash 验证数据完整性
func (p *Packet) UnMashal(data []byte) error { func (p *Packet) UnMashal(data []byte) error {
return json.Unmarshal(data, p) return json.Unmarshal(data, p)
} }
// Mashal 将自身数据编码为 []byte
// 同时生成 Hash
func (p *Packet) Mashal(src string, dst string) ([]byte, error) { func (p *Packet) Mashal(src string, dst string) ([]byte, error) {
p.DataSZ = uint32(len(p.Data)) p.DataSZ = uint32(len(p.Data))
p.Src = src p.Src = src

View File

@@ -1,5 +1,6 @@
package head package head
// Proto 类型定义
const ( const (
ProtoHello uint8 = iota ProtoHello uint8 = iota
ProtoNotify ProtoNotify

View File

@@ -3,11 +3,18 @@ package link
import "net" import "net"
var ( var (
// 本机私钥
// 利用 Curve25519 生成
// https://pkg.go.dev/golang.org/x/crypto/curve25519
// https://www.zhihu.com/question/266758647
privKey [32]byte privKey [32]byte
me net.IP // 本机虚拟 ip
myend *net.UDPAddr me net.IP
// 本机 endpoint
myend *net.UDPAddr
) )
// SetMyself 设置本机参数
func SetMyself(privateKey [32]byte, myIP string, myEndpoint string) { func SetMyself(privateKey [32]byte, myIP string, myEndpoint string) {
privKey = privateKey privKey = privateKey
var err error var err error
@@ -22,10 +29,14 @@ func SetMyself(privateKey [32]byte, myIP string, myEndpoint string) {
} }
} }
// Encode 使用 ChaCha20-Poly1305 AEAD 对称加密加密
// https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
func (l *Link) Encode(b []byte) (eb []byte, err error) { func (l *Link) Encode(b []byte) (eb []byte, err error) {
return b, nil return b, nil
} }
// Encode 使用 ChaCha20-Poly1305 AEAD 对称加密解密
// https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
func (l *Link) Decode(b []byte) (db []byte, err error) { func (l *Link) Decode(b []byte) (db []byte, err error) {
return b, nil return b, nil
} }

View File

@@ -9,16 +9,29 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// Link 是本机到 peer 的连接抽象
type Link struct { type Link struct {
PubicKey [32]byte // peer 的公钥
EndPoint string pubk [32]byte
KeepAlive int64 // peer 的公网 ip:port
pipe chan *head.Packet pep string
peerip net.IP // 决定本机是否定时向 peer 发送 hello 保持 NAT。
endpoint *net.UDPAddr // 以秒为单位,小于等于 0 不发送
allowedips []*net.IPNet keepalive int64
hasKeepRuning bool // 收到的包的队列
status int pipe chan *head.Packet
// peer 的虚拟 ip
peerip net.IP
// peer 的公网 endpoint
endpoint *net.UDPAddr
// 本机允许接收/发送的 ip 网段
allowedips []*net.IPNet
// 是否已经调用过 keepAlive
haskeepruning bool
// 是否允许转发
allowtrans bool
// 连接的状态,详见下方 const
status int
} }
const ( const (
@@ -28,11 +41,15 @@ const (
) )
var ( var (
// 本机活跃的所有连接
connections = make(map[string]*Link) connections = make(map[string]*Link)
connmapmu sync.RWMutex // 读写同步锁
myconn *net.UDPConn connmapmu sync.RWMutex
// 本机监听的 endpoint
myconn *net.UDPConn
) )
// Connect 初始化与 peer 的连接
func Connect(peer string) (*Link, error) { func Connect(peer string) (*Link, error) {
p, ok := IsInPeer(net.ParseIP(peer).String()) p, ok := IsInPeer(net.ParseIP(peer).String())
if ok { if ok {
@@ -42,6 +59,7 @@ func Connect(peer string) (*Link, error) {
return nil, errors.New("peer not exist") return nil, errors.New("peer not exist")
} }
// Close 关闭到 peer 的连接
func (l *Link) Close() { func (l *Link) Close() {
connmapmu.Lock() connmapmu.Lock()
delete(connections, l.peerip.String()) delete(connections, l.peerip.String())
@@ -49,10 +67,12 @@ func (l *Link) Close() {
l.status = LINK_STATUS_DOWN l.status = LINK_STATUS_DOWN
} }
// Read 从 peer 收包
func (l *Link) Read() *head.Packet { func (l *Link) Read() *head.Packet {
return <-l.pipe return <-l.pipe
} }
// Write 向 peer 发包
func (l *Link) Write(p *head.Packet) (n int, err error) { func (l *Link) Write(p *head.Packet) (n int, err error) {
p.Data, err = l.Encode(p.Data) p.Data, err = l.Encode(p.Data)
if err == nil { if err == nil {
@@ -60,7 +80,7 @@ func (l *Link) Write(p *head.Packet) (n int, err error) {
d, err = p.Mashal(me.String(), l.peerip.String()) d, err = p.Mashal(me.String(), l.peerip.String())
logrus.Debugln("[link] write data", string(d)) logrus.Debugln("[link] write data", string(d))
if err == nil { if err == nil {
n, err = myconn.WriteToUDP(d, l.endpoint) n, err = myconn.WriteToUDP(d, l.NextHop(l.peerip).endpoint)
} }
} }
return return

View File

@@ -7,6 +7,7 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// 监听本机 endpoint
func listen() (conn *net.UDPConn, err error) { func listen() (conn *net.UDPConn, err error) {
conn, err = net.ListenUDP("udp", myend) conn, err = net.ListenUDP("udp", myend)
if err == nil { if err == nil {
@@ -30,41 +31,47 @@ func listen() (conn *net.UDPConn, err error) {
p, ok := IsInPeer(packet.Src) p, ok := IsInPeer(packet.Src)
logrus.Infoln("[link] recv from endpoint", addr, "src", packet.Src, "dst", packet.Dst) logrus.Infoln("[link] recv from endpoint", addr, "src", packet.Src, "dst", packet.Dst)
logrus.Debugln("[link] recv:", string(lbf)) logrus.Debugln("[link] recv:", string(lbf))
if p.EndPoint == "" || p.EndPoint != addr.String() { if p.pep == "" || p.pep != addr.String() {
logrus.Infoln("[link] set endpoint of peer", p.peerip, "to", addr.String()) logrus.Infoln("[link] set endpoint of peer", p.peerip, "to", addr.String())
p.endpoint = addr p.endpoint = addr
p.EndPoint = addr.String() p.pep = addr.String()
} }
if ok && p.Accept(net.IP(packet.Dst)) { if ok {
packet.Data, err = p.Decode(packet.Data) if p.IsToMe(net.ParseIP(packet.Dst)) {
if err == nil { packet.Data, err = p.Decode(packet.Data)
switch packet.Proto { if err == nil {
case head.ProtoHello: switch packet.Proto {
switch p.status { case head.ProtoHello:
case LINK_STATUS_DOWN: switch p.status {
_, _ = p.Write(head.NewPacket(head.ProtoHello, 0, 0, nil)) case LINK_STATUS_DOWN:
logrus.Infoln("[link] send hello ack packet") _, _ = p.Write(head.NewPacket(head.ProtoHello, 0, 0, nil))
p.status = LINK_STATUS_HALFUP logrus.Infoln("[link] send hello ack packet")
case LINK_STATUS_HALFUP: p.status = LINK_STATUS_HALFUP
p.status = LINK_STATUS_UP case LINK_STATUS_HALFUP:
case LINK_STATUS_UP: p.status = LINK_STATUS_UP
case LINK_STATUS_UP:
break
}
case head.ProtoNotify:
logrus.Infoln("[link] recv notify")
onNotify(&packet)
case head.ProtoQuery:
logrus.Infoln("[link] recv query")
onQuery(&packet)
case head.ProtoData:
logrus.Infoln("[link] deliver to", p.peerip)
p.pipe <- &packet
default:
break break
} }
case head.ProtoNotify:
logrus.Infoln("[link] recv notify")
onNotify(&packet)
case head.ProtoQuery:
logrus.Infoln("[link] recv query")
onQuery(&packet)
case head.ProtoData:
logrus.Infoln("[link] deliver to", p.peerip)
p.pipe <- &packet
default:
break
} }
} else if p.Accept(net.ParseIP(packet.Dst)) && p.allowtrans {
// 转发
p.Write(&packet)
logrus.Infoln("[link] trans")
} }
} else { } else {
logrus.Infoln("[link] packet to", packet.Dst, "is refused") logrus.Infoln("[link] packet to", packet.Dst, "is refused", "(me:", me, ")")
} }
} }
} }
@@ -74,6 +81,7 @@ func listen() (conn *net.UDPConn, err error) {
return return
} }
// 从 conn 读取 sz 字节数据
func readAll(conn *net.UDPConn, sz int) ([]byte, error) { func readAll(conn *net.UDPConn, sz int) ([]byte, error) {
i := 0 i := 0
n := 0 n := 0

View File

@@ -8,11 +8,12 @@ import (
"github.com/fumiama/WireGold/gold/head" "github.com/fumiama/WireGold/gold/head"
) )
// 保持 NAT
func (l *Link) keepAlive() { func (l *Link) keepAlive() {
if l.KeepAlive > 0 && !l.hasKeepRuning { if l.keepalive > 0 && !l.haskeepruning {
l.hasKeepRuning = true l.haskeepruning = true
go func() { go func() {
t := time.NewTicker(time.Second * time.Duration(l.KeepAlive)) t := time.NewTicker(time.Second * time.Duration(l.keepalive))
for range t.C { for range t.C {
_, _ = l.Write(head.NewPacket(head.ProtoHello, 0, 0, nil)) _, _ = l.Write(head.NewPacket(head.ProtoHello, 0, 0, nil))
logrus.Infoln("[link.nat] send keep alive packet") logrus.Infoln("[link.nat] send keep alive packet")
@@ -22,10 +23,12 @@ func (l *Link) keepAlive() {
} }
} }
// 收到询问包的处理函数
func onQuery(packet *head.Packet) { func onQuery(packet *head.Packet) {
// TODO: 完成data解包与notify分发 // TODO: 完成data解包与notify分发
} }
// 收到通告包的处理函数
func onNotify(packet *head.Packet) { func onNotify(packet *head.Packet) {
// TODO: 完成data解包与endpoint注册 // TODO: 完成data解包与endpoint注册
} }

View File

@@ -6,7 +6,8 @@ import (
"github.com/fumiama/WireGold/gold/head" "github.com/fumiama/WireGold/gold/head"
) )
func AddPeer(peerip string, pubicKey [32]byte, endPoint string, allowedIPs []string, keepAlive int64) (l *Link) { // AddPeer 添加一个 peer
func AddPeer(peerip string, pubicKey [32]byte, endPoint string, allowedIPs []string, keepAlive int64, allowTrans bool) (l *Link) {
peerip = net.ParseIP(peerip).String() peerip = net.ParseIP(peerip).String()
var ok bool var ok bool
l, ok = IsInPeer(peerip) l, ok = IsInPeer(peerip)
@@ -14,17 +15,18 @@ func AddPeer(peerip string, pubicKey [32]byte, endPoint string, allowedIPs []str
return return
} }
l = &Link{ l = &Link{
PubicKey: pubicKey, pubk: pubicKey,
KeepAlive: keepAlive, keepalive: keepAlive,
pipe: make(chan *head.Packet, 32), pipe: make(chan *head.Packet, 32),
peerip: net.ParseIP(peerip), peerip: net.ParseIP(peerip),
allowtrans: allowTrans,
} }
if endPoint != "" { if endPoint != "" {
e, err := net.ResolveUDPAddr("udp", endPoint) e, err := net.ResolveUDPAddr("udp", endPoint)
if err != nil { if err != nil {
panic(err) panic(err)
} }
l.EndPoint = endPoint l.pep = endPoint
l.endpoint = e l.endpoint = e
} }
if allowedIPs != nil { if allowedIPs != nil {
@@ -42,6 +44,7 @@ func AddPeer(peerip string, pubicKey [32]byte, endPoint string, allowedIPs []str
return return
} }
// IsInPeer 查找 peer 是否已经在册
func IsInPeer(peer string) (p *Link, ok bool) { func IsInPeer(peer string) (p *Link, ok bool) {
connmapmu.RLock() connmapmu.RLock()
p, ok = connections[peer] p, ok = connections[peer]

View File

@@ -2,6 +2,7 @@ package link
import "net" import "net"
// Accept 判断是否应当接受 ip 发来的包
func (l *Link) Accept(ip net.IP) bool { func (l *Link) Accept(ip net.IP) bool {
for _, cidr := range l.allowedips { for _, cidr := range l.allowedips {
if cidr.Contains(ip) { if cidr.Contains(ip) {
@@ -11,6 +12,12 @@ func (l *Link) Accept(ip net.IP) bool {
return false return false
} }
func NextHop(ip net.IP) *Link { // IsToMe 判断是否是发给自己的包
return nil func (l *Link) IsToMe(ip net.IP) bool {
return ip.Equal(me)
}
// NextHop 得到前往 ip 的下一跳的 link
func (l *Link) NextHop(ip net.IP) *Link {
return l
} }

View File

@@ -10,7 +10,7 @@ import (
func TestTunnel(t *testing.T) { func TestTunnel(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel) logrus.SetLevel(logrus.DebugLevel)
link.SetMyself([32]byte{}, "192.168.1.2", "127.0.0.1:1236") link.SetMyself([32]byte{}, "192.168.1.2", "127.0.0.1:1236")
link.AddPeer("192.168.1.2", [32]byte{}, "127.0.0.1:1236", nil, 0) link.AddPeer("192.168.1.2", [32]byte{}, "127.0.0.1:1236", nil, 0, false)
tunn, err := Create("192.168.1.2", 1, 1) tunn, err := Create("192.168.1.2", 1, 1)
if err != nil { if err != nil {
t.Error(err) t.Error(err)