mirror of
https://github.com/fumiama/WireGold.git
synced 2026-06-04 23:40:26 +08:00
完善主程序
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,4 +14,5 @@
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
config.yaml
|
||||
|
||||
41
config/cfg.go
Normal file
41
config/cfg.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Config WireGold 配置文件
|
||||
type Config struct {
|
||||
IP string `yaml:"IP"`
|
||||
SubNet string `yaml:"SubNet"`
|
||||
PrivateKey string `yaml:"PrivateKey"`
|
||||
EndPoint string `yaml:"EndPoint"`
|
||||
Peers []Peer `yaml:"Peers"`
|
||||
}
|
||||
|
||||
// Peer 对端信息
|
||||
type Peer struct {
|
||||
IP string `yaml:"IP"`
|
||||
SubNet string `yaml:"SubNet"`
|
||||
PublicKey string `yaml:"PublicKey"`
|
||||
EndPoint string `yaml:"EndPoint"`
|
||||
AllowedIPs []string `yaml:"AllowedIPs"`
|
||||
KeepAliveSeconds int64 `yaml:"KeepAliveSeconds"`
|
||||
AllowTrans bool `yaml:"AllowTrans"`
|
||||
}
|
||||
|
||||
func Parse(path string) (c Config) {
|
||||
file, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatal("open config file failed:", err)
|
||||
}
|
||||
err = yaml.NewDecoder(bytes.NewReader(file)).Decode(&c)
|
||||
if err != nil {
|
||||
log.Fatal("invalid config file:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
3
go.mod
3
go.mod
@@ -3,8 +3,11 @@ module github.com/fumiama/WireGold
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/fumiama/go-base16384 v1.2.1
|
||||
github.com/fumiama/go-x25519 v1.0.0
|
||||
github.com/fumiama/gofastTEA v0.0.6
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
39
go.sum
39
go.sum
@@ -3,43 +3,80 @@ github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqe
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fumiama/go-base16384 v1.2.1 h1:6OGprW8g/95m2ocmryHi8mipZ7bx9StFMZDKEqLvMiA=
|
||||
github.com/fumiama/go-base16384 v1.2.1/go.mod h1:1HTC0QFL7BjS0DuO5Qm+fBYKQkHqmAapLbRpCxrhPXQ=
|
||||
github.com/fumiama/go-x25519 v1.0.0 h1:hiGg9EhseVmGCc8T1jECVkj8Keu/aJ1ZK05RM8Vuavo=
|
||||
github.com/fumiama/go-x25519 v1.0.0/go.mod h1:8VOhfyGZzw4IUs4nCjQFqW9cA3V/QpSCtP3fo2dLNg4=
|
||||
github.com/fumiama/gofastTEA v0.0.6 h1:Yni3MXDbJVa/c4CecgdZDgCJK+fLdvGph+OBqY2mtiI=
|
||||
github.com/fumiama/gofastTEA v0.0.6/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
|
||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.3.2 h1:EFZNb3awNbwxRtmDkWv3PH6Z9rUV6ZLFa3hBmRMRRCA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/HNXXayIpwI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"unsafe"
|
||||
|
||||
tea "github.com/fumiama/gofastTEA"
|
||||
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
)
|
||||
|
||||
// Me 是本机的抽象
|
||||
@@ -29,10 +31,12 @@ type Me struct {
|
||||
myconn *net.UDPConn
|
||||
// 本机路由表
|
||||
router *Router
|
||||
// 不分目的 link 的接收队列
|
||||
pipe chan *head.Packet
|
||||
}
|
||||
|
||||
// NewMe 设置本机参数
|
||||
func NewMe(privateKey *[32]byte, myipwithmask string, myEndpoint string) (m Me) {
|
||||
func NewMe(privateKey *[32]byte, myipwithmask string, myEndpoint string, nopipeinlink bool) (m Me) {
|
||||
m.privKey = *privateKey
|
||||
var err error
|
||||
m.myend, err = net.ResolveUDPAddr("udp", myEndpoint)
|
||||
@@ -55,6 +59,10 @@ func NewMe(privateKey *[32]byte, myipwithmask string, myEndpoint string) (m Me)
|
||||
table: make(map[string]*Link, 16),
|
||||
}
|
||||
m.router.SetDefault(nil)
|
||||
if nopipeinlink {
|
||||
m.pipe = make(chan *head.Packet, 32)
|
||||
}
|
||||
m.AddPeer(m.me.String(), nil, "127.0.0.1:56789", []string{myipwithmask, "127.0.0.0/8"}, 0, false, nopipeinlink)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -56,10 +56,14 @@ func (m *Me) Connect(peer string) (*Link, error) {
|
||||
|
||||
// Close 关闭到 peer 的连接
|
||||
func (l *Link) Close() {
|
||||
l.status = LINK_STATUS_DOWN
|
||||
}
|
||||
|
||||
// Destroy 从 connections 移除 peer
|
||||
func (l *Link) Destroy() {
|
||||
l.me.connmapmu.Lock()
|
||||
delete(l.me.connections, l.peerip.String())
|
||||
l.me.connmapmu.Unlock()
|
||||
l.status = LINK_STATUS_DOWN
|
||||
}
|
||||
|
||||
// Read 从 peer 收包
|
||||
|
||||
@@ -61,7 +61,11 @@ func (m *Me) listen() (conn *net.UDPConn, err error) {
|
||||
p.onQuery(&packet)
|
||||
case head.ProtoData:
|
||||
logrus.Infoln("[link] deliver to", p.peerip)
|
||||
p.pipe <- &packet
|
||||
if p.pipe != nil {
|
||||
p.pipe <- &packet
|
||||
} else {
|
||||
m.pipe <- &packet
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -84,6 +88,12 @@ func (m *Me) listen() (conn *net.UDPConn, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Read 接收所有发送给本机的报文
|
||||
// 需要开启 nopipe
|
||||
func (m *Me) Read() *head.Packet {
|
||||
return <-m.pipe
|
||||
}
|
||||
|
||||
// 从 conn 读取 sz 字节数据
|
||||
func readAll(conn *net.UDPConn, sz int) ([]byte, error) {
|
||||
i := 0
|
||||
|
||||
@@ -4,13 +4,13 @@ import (
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
curve "github.com/fumiama/go-x25519"
|
||||
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
curve "github.com/fumiama/go-x25519"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AddPeer 添加一个 peer
|
||||
func (m *Me) AddPeer(peerip string, pubicKey *[32]byte, endPoint string, allowedIPs []string, keepAlive int64, allowTrans bool) (l *Link) {
|
||||
func (m *Me) AddPeer(peerip string, pubicKey *[32]byte, endPoint string, allowedIPs []string, keepAlive int64, allowTrans, nopipe bool) (l *Link) {
|
||||
peerip = net.ParseIP(peerip).String()
|
||||
var ok bool
|
||||
l, ok = m.IsInPeer(peerip)
|
||||
@@ -20,11 +20,13 @@ func (m *Me) AddPeer(peerip string, pubicKey *[32]byte, endPoint string, allowed
|
||||
l = &Link{
|
||||
pubk: pubicKey,
|
||||
keepalive: keepAlive,
|
||||
pipe: make(chan *head.Packet, 32),
|
||||
peerip: net.ParseIP(peerip),
|
||||
allowtrans: allowTrans,
|
||||
me: m,
|
||||
}
|
||||
if !nopipe {
|
||||
l.pipe = make(chan *head.Packet, 32)
|
||||
}
|
||||
if pubicKey != nil {
|
||||
c := curve.Get(m.privKey[:])
|
||||
k, err := c.Shared(pubicKey)
|
||||
@@ -53,6 +55,7 @@ func (m *Me) AddPeer(peerip string, pubicKey *[32]byte, endPoint string, allowed
|
||||
l.me.connmapmu.Lock()
|
||||
l.me.connections[peerip] = l
|
||||
l.me.connmapmu.Unlock()
|
||||
logrus.Infoln("[peer] add peer:", peerip, "allow:", allowedIPs)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
32
helper/data.go
Normal file
32
helper/data.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// slice is the runtime representation of a slice.
|
||||
// It cannot be used safely or portably and its representation may
|
||||
// change in a later release.
|
||||
//
|
||||
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
|
||||
// data it references will not be garbage collected.
|
||||
type slice struct {
|
||||
data unsafe.Pointer
|
||||
len int
|
||||
cap int
|
||||
}
|
||||
|
||||
// BytesToString 没有内存开销的转换
|
||||
func BytesToString(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// StringToBytes 没有内存开销的转换
|
||||
func StringToBytes(s string) (b []byte) {
|
||||
bh := (*slice)(unsafe.Pointer(&b))
|
||||
sh := (*slice)(unsafe.Pointer(&s)) // 不要访问 sh.cap
|
||||
bh.data = sh.data
|
||||
bh.len = sh.len
|
||||
bh.cap = sh.len
|
||||
return b
|
||||
}
|
||||
15
helper/file.go
Normal file
15
helper/file.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package helper
|
||||
|
||||
import "os"
|
||||
|
||||
// IsExist 文件/路径存在
|
||||
func IsExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// IsNotExist 文件/路径不存在
|
||||
func IsNotExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err != nil && os.IsNotExist(err)
|
||||
}
|
||||
109
lower/nic.go
Normal file
109
lower/nic.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package lower
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/songgao/water"
|
||||
"github.com/songgao/water/waterutil"
|
||||
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
)
|
||||
|
||||
// NIC 虚拟网卡
|
||||
type NIC struct {
|
||||
ifce *water.Interface
|
||||
ip string
|
||||
subnet string
|
||||
hasstart bool
|
||||
}
|
||||
|
||||
// NewNIC 新建 TUN 网络接口卡
|
||||
// 网卡地址为 ip, 所属子网为 subnet
|
||||
func NewNIC(ip, subnet string) (n *NIC) {
|
||||
ifce, err := water.New(water.Config{DeviceType: water.TUN})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n = &NIC{
|
||||
ifce: ifce,
|
||||
ip: ip,
|
||||
subnet: subnet,
|
||||
}
|
||||
n.prepare()
|
||||
return
|
||||
}
|
||||
|
||||
// Start 开始处理网卡消息,阻塞
|
||||
func (nc *NIC) Start(m *link.Me) {
|
||||
if nc.hasstart {
|
||||
return
|
||||
}
|
||||
nc.hasstart = true
|
||||
go func() { // 接收到 NIC
|
||||
for nc.hasstart {
|
||||
packet := m.Read()
|
||||
logrus.Infoln("[lower] recv", len(packet.Data), "bytes packet")
|
||||
if !waterutil.IsIPv4(packet.Data) {
|
||||
logrus.Warnln("[lower] recv recv non-ipv4 packet")
|
||||
continue
|
||||
}
|
||||
_, err := nc.ifce.Write(packet.Data)
|
||||
if err != nil {
|
||||
logrus.Errorln("[lower] recv write to nic err:", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 4096)
|
||||
for nc.hasstart { // 从 NIC 发送
|
||||
packet := buf
|
||||
n, err := nc.ifce.Read(packet)
|
||||
if err != nil {
|
||||
logrus.Errorln("[lower] send read from nic err:", err)
|
||||
break
|
||||
}
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
packet = packet[:n]
|
||||
if !waterutil.IsIPv4(packet) {
|
||||
logrus.Warnln("[lower] send recv non-ipv4 packet")
|
||||
continue
|
||||
}
|
||||
logrus.Infoln("[lower] send", n, "bytes packet")
|
||||
dst := waterutil.IPv4Destination(packet)
|
||||
srcport := waterutil.IPv4SourcePort(packet)
|
||||
dstport := waterutil.IPv4DestinationPort(packet)
|
||||
lnk, err := m.Connect(dst.String())
|
||||
if err != nil {
|
||||
logrus.Errorln("[lower] connect to peer err:", err)
|
||||
continue
|
||||
}
|
||||
lnk.Write(head.NewPacket(head.ProtoData, srcport, dstport, packet))
|
||||
}
|
||||
}
|
||||
|
||||
// Stop 停止处理
|
||||
func (n *NIC) Stop() {
|
||||
n.hasstart = false
|
||||
}
|
||||
|
||||
// Destroy 关闭网卡
|
||||
func (n *NIC) Destroy() error {
|
||||
return n.ifce.Close()
|
||||
}
|
||||
|
||||
func execute(c string, args ...string) {
|
||||
logrus.Printf("[lower] exec cmd: %v %v:", c, args)
|
||||
cmd := exec.Command(c, args...)
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stdin = os.Stdin
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
logrus.Panicln("[lower] failed to exec cmd:", err)
|
||||
}
|
||||
}
|
||||
17
lower/tun_darwin.go
Normal file
17
lower/tun_darwin.go
Normal file
@@ -0,0 +1,17 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package lower
|
||||
|
||||
func (n *NIC) prepare() {
|
||||
execute("ifconfig", n.ifce.Name(), "inet", n.ip, n.ip, "up")
|
||||
execute("route", "add", n.subnet, "-interface", n.ifce.Name())
|
||||
}
|
||||
|
||||
func (n *NIC) Up() {
|
||||
execute("ifconfig", n.ifce.Name(), "inet", n.ip, n.ip, "up")
|
||||
}
|
||||
|
||||
func (n *NIC) Down() {
|
||||
execute("ifconfig", n.ifce.Name(), "down")
|
||||
}
|
||||
18
lower/tun_linux.go
Normal file
18
lower/tun_linux.go
Normal file
@@ -0,0 +1,18 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package lower
|
||||
|
||||
func (n *NIC) prepare() {
|
||||
execute("/sbin/ip", "link", "set", "dev", ifcename, "mtu", "1500")
|
||||
execute("/sbin/ip", "addr", "add", ip, "dev", ifcename)
|
||||
execute("/sbin/ip", "route", "add", subnet, "dev", ifcename)
|
||||
}
|
||||
|
||||
func (n *NIC) Up() {
|
||||
execute("/sbin/ip", "link", "set", "dev", ifcename, "up")
|
||||
}
|
||||
|
||||
func (n *NIC) Down() {
|
||||
execute("/sbin/ip", "link", "set", "dev", ifcename, "down")
|
||||
}
|
||||
16
lower/tun_stub.go
Normal file
16
lower/tun_stub.go
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build !darwin && !linux && !windows
|
||||
// +build !darwin,!linux,!windows
|
||||
|
||||
package lower
|
||||
|
||||
func (n *NIC) prepare() {
|
||||
panic("not support this os now")
|
||||
}
|
||||
|
||||
func (n *NIC) Up() {
|
||||
panic("not support this os now")
|
||||
}
|
||||
|
||||
func (n *NIC) Down() {
|
||||
panic("not support this os now")
|
||||
}
|
||||
18
lower/tun_windows.go
Normal file
18
lower/tun_windows.go
Normal file
@@ -0,0 +1,18 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package lower
|
||||
|
||||
func (n *NIC) prepare() {
|
||||
execute("/sbin/ip", "link", "set", "dev", ifcename, "mtu", "1500")
|
||||
execute("/sbin/ip", "addr", "add", ip, "dev", ifcename)
|
||||
execute("/sbin/ip", "route", "add", subnet, "dev", ifcename)
|
||||
}
|
||||
|
||||
func (n *NIC) Up() {
|
||||
execute("/sbin/ip", "link", "set", "dev", ifcename, "up")
|
||||
}
|
||||
|
||||
func (n *NIC) Down() {
|
||||
execute("/sbin/ip", "link", "set", "dev", ifcename, "down")
|
||||
}
|
||||
145
main.go
145
main.go
@@ -1 +1,146 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
base14 "github.com/fumiama/go-base16384"
|
||||
curve "github.com/fumiama/go-x25519"
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
"github.com/fumiama/WireGold/helper"
|
||||
"github.com/fumiama/WireGold/lower"
|
||||
)
|
||||
|
||||
const suffix32 = "㴄"
|
||||
|
||||
func main() {
|
||||
help := flag.Bool("h", false, "display this help")
|
||||
gen := flag.Bool("g", false, "generate key pair")
|
||||
showp := flag.Bool("p", false, "show my publickey")
|
||||
file := flag.String("c", "config.yaml", "specify conf file")
|
||||
flag.Parse()
|
||||
if *help {
|
||||
displayHelp("")
|
||||
}
|
||||
if *gen {
|
||||
k, err := curve.New(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubk, err := base14.UTF16be2utf8(base14.Encode((*k.Public())[:]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
prvk, err := base14.UTF16be2utf8(base14.Encode((*k.Private())[:]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("PublicKey:", helper.BytesToString(pubk[:57]))
|
||||
fmt.Println("PrivateKey:", helper.BytesToString(prvk[:57]))
|
||||
os.Exit(0)
|
||||
}
|
||||
if helper.IsNotExist(*file) {
|
||||
f, err := os.Create(*file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var r string
|
||||
fmt.Print("IP: ")
|
||||
fmt.Scanln(&r)
|
||||
if r == "" {
|
||||
f.Close()
|
||||
os.Remove(*file)
|
||||
fmt.Println("nil ip")
|
||||
return
|
||||
}
|
||||
f.WriteString("IP: " + r + "\n")
|
||||
r = ""
|
||||
|
||||
fmt.Print("SubNet: ")
|
||||
fmt.Scanln(&r)
|
||||
if r == "" {
|
||||
f.Close()
|
||||
os.Remove(*file)
|
||||
fmt.Println("nil subnet")
|
||||
return
|
||||
}
|
||||
f.WriteString("SubNet: " + r + "\n")
|
||||
r = ""
|
||||
|
||||
fmt.Print("PrivateKey: ")
|
||||
fmt.Scanln(&r)
|
||||
if r == "" {
|
||||
f.Close()
|
||||
os.Remove(*file)
|
||||
fmt.Println("nil private key")
|
||||
return
|
||||
}
|
||||
f.WriteString("PrivateKey: " + r + "\n")
|
||||
r = ""
|
||||
|
||||
fmt.Print("EndPoint: ")
|
||||
fmt.Scanln(&r)
|
||||
if r == "" {
|
||||
f.Close()
|
||||
os.Remove(*file)
|
||||
fmt.Println("nil endpoint")
|
||||
return
|
||||
}
|
||||
f.WriteString("EndPoint: " + r + "\n")
|
||||
r = ""
|
||||
|
||||
f.Close()
|
||||
}
|
||||
c := config.Parse(*file)
|
||||
if c.IP == "" {
|
||||
displayHelp("nil ip")
|
||||
}
|
||||
if c.SubNet == "" {
|
||||
displayHelp("nil subnet")
|
||||
}
|
||||
if c.PrivateKey == "" {
|
||||
displayHelp("nil private key")
|
||||
}
|
||||
if c.EndPoint == "" {
|
||||
displayHelp("nil endpoint")
|
||||
}
|
||||
var key [32]byte
|
||||
k, err := base14.UTF82utf16be(helper.StringToBytes(c.PrivateKey + suffix32))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n := copy(key[:], base14.Decode(k))
|
||||
if n != 32 {
|
||||
displayHelp("private key length is not 32")
|
||||
}
|
||||
|
||||
if *showp {
|
||||
c := curve.Get(key[:])
|
||||
pubk, err := base14.UTF16be2utf8(base14.Encode((*c.Public())[:]))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("PublicKey:", helper.BytesToString(pubk[:57]))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
nic := lower.NewNIC(c.IP, c.SubNet)
|
||||
me := link.NewMe(&key, c.IP+"/32", c.EndPoint, true)
|
||||
nic.Up()
|
||||
defer func() {
|
||||
nic.Stop()
|
||||
nic.Down()
|
||||
nic.Destroy()
|
||||
}()
|
||||
|
||||
nic.Start(&me)
|
||||
}
|
||||
|
||||
func displayHelp(hint string) {
|
||||
fmt.Println(hint)
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,15 @@ package upper
|
||||
|
||||
import "io"
|
||||
|
||||
// 常用服务端口
|
||||
const (
|
||||
// ServiceNull 不在意端口号的服务
|
||||
ServiceNull = iota
|
||||
// ServiceTunnel 管道通信服务
|
||||
ServiceTunnel
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Create(peer string, srcport uint16, destport uint16) (Service, error)
|
||||
Create(peer string, srcport, destport, mtu uint16) (Service, error)
|
||||
io.ReadWriteCloser
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ func TestTunnel(t *testing.T) {
|
||||
t.Log("peer priv key:", hex.EncodeToString(peerpk.Private()[:]))
|
||||
t.Log("peer publ key:", hex.EncodeToString(peerpk.Public()[:]))
|
||||
|
||||
m := link.NewMe(selfpk.Private(), "192.168.1.2", "127.0.0.1:1236")
|
||||
m.AddPeer("192.168.1.3", peerpk.Public(), "127.0.0.1:1237", []string{"192.168.1.3/32"}, 0, false)
|
||||
p := link.NewMe(peerpk.Private(), "192.168.1.3", "127.0.0.1:1237")
|
||||
p.AddPeer("192.168.1.2", selfpk.Public(), "127.0.0.1:1236", []string{"192.168.1.2/32"}, 0, false)
|
||||
m := link.NewMe(selfpk.Private(), "192.168.1.2/32", "127.0.0.1:1236", false)
|
||||
m.AddPeer("192.168.1.3", peerpk.Public(), "127.0.0.1:1237", []string{"192.168.1.3/32"}, 0, false, false)
|
||||
p := link.NewMe(peerpk.Private(), "192.168.1.3/32", "127.0.0.1:1237", false)
|
||||
p.AddPeer("192.168.1.2", selfpk.Public(), "127.0.0.1:1236", []string{"192.168.1.2/32"}, 0, false, false)
|
||||
tunnme, err := Create(&m, "192.168.1.3", 1, 1, 4096)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user