mirror of
https://github.com/liloew/gvn.git
synced 2025-12-24 13:38:00 +08:00
workable on macOS/Linux
This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -23,7 +23,7 @@
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "main.go",
|
||||
"args": ["up", "-c", "/tmp/ALTGVN/client.yaml"],
|
||||
"args": ["up", "-c", "conf/client-1.yaml"],
|
||||
}, {
|
||||
"name": "Debug cobra cli - up server",
|
||||
"type": "go",
|
||||
|
||||
15
cmd/up.go
15
cmd/up.go
@@ -16,7 +16,6 @@ limitations under the License.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -30,6 +29,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/protocol"
|
||||
"github.com/liloew/altgvn/dhcp"
|
||||
"github.com/liloew/altgvn/p2p"
|
||||
"github.com/liloew/altgvn/route"
|
||||
"github.com/liloew/altgvn/tun"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/songgao/packets/ethernet"
|
||||
@@ -93,8 +93,7 @@ func upCommand(cmd *cobra.Command) {
|
||||
"RemoteAddr": stream.Conn().RemoteMultiaddr(),
|
||||
"Protocol": stream.Protocol(),
|
||||
}).Info("handler new stream")
|
||||
rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))
|
||||
go readData(stream, rw)
|
||||
go readData(stream)
|
||||
})
|
||||
|
||||
var bootstraps []string
|
||||
@@ -155,7 +154,7 @@ func upCommand(cmd *cobra.Command) {
|
||||
"ID": r.Id,
|
||||
"Subnet": r.Subnets,
|
||||
}).Info("Refresh local vip table")
|
||||
p2p.RouteTable.AddByString(strings.Split(r.Ip, "/")[0]+"/32", r.Id)
|
||||
route.RouteTable.AddByString(strings.Split(r.Ip, "/")[0]+"/32", r.Id)
|
||||
if r.Id != host.ID().Pretty() {
|
||||
subnets = append(subnets, r.Subnets...)
|
||||
}
|
||||
@@ -244,7 +243,7 @@ func upCommand(cmd *cobra.Command) {
|
||||
select {}
|
||||
}
|
||||
|
||||
func readData(stream network.Stream, rw *bufio.ReadWriter) {
|
||||
func readData(stream network.Stream) {
|
||||
for {
|
||||
var psize = make([]byte, 2)
|
||||
if _, err := stream.Read(psize); err != nil {
|
||||
@@ -258,10 +257,8 @@ func readData(stream network.Stream, rw *bufio.ReadWriter) {
|
||||
"ERROR": err,
|
||||
"SIZE": n,
|
||||
}).Error("Read data error")
|
||||
if err.Error() == "EOF" {
|
||||
break
|
||||
}
|
||||
continue
|
||||
stream.Close()
|
||||
break
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"LocalPeer": stream.Conn().LocalPeer().Pretty(),
|
||||
|
||||
@@ -4,7 +4,7 @@ dev:
|
||||
name: utun4
|
||||
mtu: 1420
|
||||
subnets:
|
||||
- 10.30.20.0/24
|
||||
- 10.30.22.0/24
|
||||
- 172.16.13.0/24
|
||||
version: 1.0.0
|
||||
priKey: !!binary |
|
||||
|
||||
@@ -4,7 +4,7 @@ dev:
|
||||
name: utun4
|
||||
mtu: 1420
|
||||
subnets:
|
||||
- 10.30.21.0/24
|
||||
# - 10.30.21.0/24
|
||||
version: 1.0.0
|
||||
priKey: !!binary |
|
||||
CAASqAkwggSkAgEAAoIBAQDjbJ/cot0GYydpfzQ5B1KZsQ6OgcVZoBMUXRn81btTJlFCqZ
|
||||
|
||||
@@ -6,7 +6,7 @@ dev:
|
||||
vip: 192.168.1.1/24
|
||||
mtu: 1500
|
||||
subnets:
|
||||
#- "10.30.22.0/24"
|
||||
- 10.30.20.0/24
|
||||
version: 1.0.0
|
||||
priKey: !!binary |
|
||||
CAASpwkwggSjAgEAAoIBAQC3pxvCIViNopIFRoDRvngT3AEfPheSYuPbd8I1AZMTKoqgip
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/libp2p/go-libp2p-core/protocol"
|
||||
rpc "github.com/libp2p/go-libp2p-gorpc"
|
||||
"github.com/liloew/altgvn/p2p"
|
||||
"github.com/liloew/altgvn/route"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -100,7 +100,7 @@ func (s *DHCPService) DHCP(ctx context.Context, req Request, res *Response) erro
|
||||
}).Info("RPC - Client requested data")
|
||||
|
||||
// vip/mask -> vip/32
|
||||
p2p.RouteTable.AddByString(strings.Split(data.Ip, "/")[0]+"/32", data.Id)
|
||||
route.RouteTable.AddByString(strings.Split(data.Ip, "/")[0]+"/32", data.Id)
|
||||
mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
107
p2p/peer.go
107
p2p/peer.go
@@ -14,10 +14,12 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/host"
|
||||
"github.com/libp2p/go-libp2p-core/network"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/liloew/altgvn/dhcp"
|
||||
"github.com/liloew/altgvn/route"
|
||||
"github.com/liloew/altgvn/tun"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/songgao/water/waterutil"
|
||||
"github.com/zmap/go-iptree/iptree"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type MessageType uint
|
||||
@@ -46,9 +48,8 @@ type Message struct {
|
||||
}
|
||||
|
||||
var (
|
||||
RouteTable = iptree.New()
|
||||
Streams = make(map[string]network.Stream)
|
||||
VIP string
|
||||
Streams = make(map[string]network.Stream)
|
||||
VIP string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -104,9 +105,6 @@ func NewPubSub(host host.Host, topic string) *Publisher {
|
||||
for {
|
||||
if msg, err := sub.Next(context.Background()); err == nil {
|
||||
message := new(Message)
|
||||
if msg.ReceivedFrom.Pretty() == host.ID().Pretty() {
|
||||
continue
|
||||
}
|
||||
if err := json.Unmarshal(msg.Data, message); err != nil {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"ERROR": err,
|
||||
@@ -116,12 +114,49 @@ func NewPubSub(host host.Host, topic string) *Publisher {
|
||||
"Message": message,
|
||||
}).Info("Receive message from topic")
|
||||
if message.MessageType == MessageTypeRoute {
|
||||
if msg.ReceivedFrom.Pretty() == host.ID().Pretty() {
|
||||
continue
|
||||
}
|
||||
// TODO: add MASQUERADE if self
|
||||
tun.RefreshRoute(message.Subnets)
|
||||
for _, subnet := range message.Subnets {
|
||||
// Add will override the exist one
|
||||
RouteTable.AddByString(strings.TrimSpace(subnet), message.Id)
|
||||
route.RouteTable.AddByString(strings.TrimSpace(subnet), message.Id)
|
||||
}
|
||||
} else if message.MessageType == MessageTypeOnline {
|
||||
// route.RouteTable.AddByString(strings.Split(message.Vip, "/")[0]+"/32", message.Id)
|
||||
// refresh clients
|
||||
if viper.GetUint("mode") == 1 {
|
||||
// server
|
||||
continue
|
||||
} else {
|
||||
req := dhcp.Request{}
|
||||
var ress []dhcp.Response
|
||||
if err := dhcp.Call("DHCPService", "Clients", req, &ress); err == nil {
|
||||
subnets := make([]string, 0)
|
||||
for _, r := range ress {
|
||||
if r.Id == host.ID().Pretty() {
|
||||
continue
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"VIP": r.Ip,
|
||||
"ID": r.Id,
|
||||
"Subnet": r.Subnets,
|
||||
}).Info("Refresh local vip table")
|
||||
route.RouteTable.AddByString(strings.Split(r.Ip, "/")[0]+"/32", r.Id)
|
||||
if r.Id != host.ID().Pretty() {
|
||||
subnets = append(subnets, r.Subnets...)
|
||||
}
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"subnets": subnets,
|
||||
}).Info("Refresh subnets")
|
||||
tun.RefreshRoute(subnets)
|
||||
}
|
||||
|
||||
}
|
||||
} else if message.MessageType == MessageTypeOffline {
|
||||
route.RouteTable.DeleteByString(strings.Split(message.Vip, "/")[0] + "/32")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -141,41 +176,43 @@ func NewPubSub(host host.Host, topic string) *Publisher {
|
||||
}
|
||||
|
||||
func (p *Publisher) Publish(peerId string, vip string, subnets []string) {
|
||||
message := &Message{
|
||||
Id: peerId,
|
||||
MessageType: MessageTypeRoute,
|
||||
Vip: vip,
|
||||
}
|
||||
if len(subnets) > 0 {
|
||||
message := &Message{
|
||||
Id: peerId,
|
||||
MessageType: MessageTypeRoute,
|
||||
Vip: vip,
|
||||
Subnets: subnets,
|
||||
}
|
||||
if bytes, err := json.Marshal(message); err == nil {
|
||||
ticker := time.NewTicker(10 * time.Second)
|
||||
go func(tk *time.Ticker) {
|
||||
interval := 10
|
||||
for _ = range tk.C {
|
||||
if err := p.pub.Publish(context.Background(), bytes); err != nil {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"ERROR": err,
|
||||
"Message": message,
|
||||
}).Error("Publish message from to topic error")
|
||||
}
|
||||
if interval < 30*60 {
|
||||
// half of hour for the longest
|
||||
interval *= 2
|
||||
}
|
||||
message.Subnets = subnets
|
||||
} else {
|
||||
message.MessageType = MessageTypeOnline
|
||||
}
|
||||
if bytes, err := json.Marshal(message); err == nil {
|
||||
ticker := time.NewTicker(10 * time.Second)
|
||||
go func(tk *time.Ticker) {
|
||||
interval := 10
|
||||
for _ = range tk.C {
|
||||
if err := p.pub.Publish(context.Background(), bytes); err != nil {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"Interval": interval,
|
||||
}).Info("")
|
||||
ticker.Reset(time.Duration(interval) * time.Second)
|
||||
"ERROR": err,
|
||||
"Message": message,
|
||||
}).Error("Publish message from to topic error")
|
||||
}
|
||||
}(ticker)
|
||||
}
|
||||
if interval < 30*60 {
|
||||
// half of hour for the longest
|
||||
interval *= 2
|
||||
}
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"Interval": interval,
|
||||
}).Info("")
|
||||
ticker.Reset(time.Duration(interval) * time.Second)
|
||||
}
|
||||
}(ticker)
|
||||
}
|
||||
}
|
||||
|
||||
func ForwardPacket(host host.Host, zone string, packets []byte, vipNet *net.IPNet) {
|
||||
dst := waterutil.IPv4Destination(packets)
|
||||
if peerId, found, err := RouteTable.GetByString(dst.String()); err == nil && found {
|
||||
if peerId, found, err := route.RouteTable.GetByString(dst.String()); err == nil && found {
|
||||
if stream, ok := Streams[peerId.(string)]; ok {
|
||||
binary.Write(stream, binary.LittleEndian, uint16(len(packets)))
|
||||
if n, err := stream.Write(packets); n != len(packets) || err != nil {
|
||||
|
||||
9
route/routeTable.go
Normal file
9
route/routeTable.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"github.com/zmap/go-iptree/iptree"
|
||||
)
|
||||
|
||||
var (
|
||||
RouteTable = iptree.New()
|
||||
)
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -134,7 +135,7 @@ fi`
|
||||
return err
|
||||
}
|
||||
// remove if success otherwise for debug
|
||||
// defer os.Remove(tmpfile.Name())
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -246,7 +247,7 @@ fi`
|
||||
return err
|
||||
}
|
||||
// remove if success otherwise for debug
|
||||
// defer os.Remove(tmpfile.Name())
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -319,7 +320,7 @@ fi`
|
||||
return err
|
||||
}
|
||||
// remove if success otherwise for debug
|
||||
// defer os.Remove(tmpfile.Name())
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -391,7 +392,7 @@ fi`
|
||||
return err
|
||||
}
|
||||
// remove if success otherwise for debug
|
||||
// defer os.Remove(tmpfile.Name())
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ func ConfigAddr(dev Device) error {
|
||||
"COMMAND": content,
|
||||
}).Debug("Execute command")
|
||||
|
||||
if err := RunCommand(tmpfile.Name()); err == nil {
|
||||
// remove if success otherwise for debug
|
||||
defer os.Remove(tmpfile.Name())
|
||||
if err := RunCommand(tmpfile.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove if success otherwise for debug
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -97,9 +97,10 @@ func RemoveRoute(subnets []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := RunCommand(tmpfile.Name()); err == nil {
|
||||
defer os.Remove(tmpfile.Name())
|
||||
if err := RunCommand(tmpfile.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -143,10 +144,10 @@ func AddRoute(subnets []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := RunCommand(tmpfile.Name()); err == nil {
|
||||
defer os.Remove(tmpfile.Name())
|
||||
if err := RunCommand(tmpfile.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(tmpfile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user