This commit is contained in:
jdl
2025-01-02 07:42:00 +01:00
parent 5d97cccb98
commit f0076939d5
12 changed files with 131 additions and 197 deletions

View File

@@ -56,7 +56,7 @@ func storeJson(x any, outPath string) error {
return os.Rename(tmpPath, outPath)
}
func storePeerConfig(netName string, pc m.PeerConfig) error {
func storePeerConfig(netName string, pc localConfig) error {
return storeJson(pc, peerConfigPath(netName))
}
@@ -73,7 +73,7 @@ func loadJson(dataPath string, ptr any) error {
return json.Unmarshal(data, ptr)
}
func loadPeerConfig(netName string) (pc m.PeerConfig, err error) {
func loadPeerConfig(netName string) (pc localConfig, err error) {
return pc, loadJson(peerConfigPath(netName), &pc)
}

View File

@@ -3,6 +3,7 @@ package node
import (
"net"
"net/netip"
"net/url"
"sync/atomic"
"time"
)
@@ -33,6 +34,9 @@ type peerRoute struct {
}
var (
hubURL *url.URL
apiKey string
// Configuration for this peer.
netName string
localIP byte

View File

@@ -5,7 +5,6 @@ import (
"io"
"log"
"net/http"
"net/url"
"time"
"vppn/m"
)
@@ -16,21 +15,18 @@ type hubPoller struct {
versions [256]int64
}
func newHubPoller(conf m.PeerConfig) *hubPoller {
u, err := url.Parse(conf.HubAddress)
if err != nil {
log.Fatalf("Failed to parse hub address %s: %v", conf.HubAddress, err)
}
func newHubPoller() *hubPoller {
u := *hubURL
u.Path = "/peer/fetch-state/"
client := &http.Client{Timeout: 8 * time.Second}
req := &http.Request{
Method: http.MethodGet,
URL: u,
URL: &u,
Header: http.Header{},
}
req.SetBasicAuth("", conf.APIKey)
req.SetBasicAuth("", apiKey)
return &hubPoller{
client: client,
@@ -71,7 +67,7 @@ func (hp *hubPoller) pollHub() {
}
if err := json.Unmarshal(body, &state); err != nil {
log.Printf("Failed to unmarshal response from hub: %v", err)
log.Printf("Failed to unmarshal response from hub: %v\n%s", err, body)
return
}

View File

@@ -1,6 +1,8 @@
package node
import (
"bytes"
"crypto/rand"
"encoding/json"
"flag"
"fmt"
@@ -9,10 +11,14 @@ import (
"net"
"net/http"
"net/netip"
"net/url"
"os"
"runtime/debug"
"time"
"vppn/m"
"golang.org/x/crypto/nacl/box"
"golang.org/x/crypto/nacl/sign"
)
func panicHandler() {
@@ -24,33 +30,61 @@ func panicHandler() {
func Main() {
defer panicHandler()
var (
initURL string
listenIP string
)
var hubAddress string
flag.StringVar(&netName, "name", "", "[REQUIRED] The network name.")
flag.StringVar(&initURL, "init-url", "", "Initializes peer from the hub URL.")
flag.StringVar(&listenIP, "listen-ip", "", "IP address to listen on.")
flag.StringVar(&hubAddress, "hub-address", "", "[REQUIRED] The hub address.")
flag.StringVar(&apiKey, "api-key", "", "[REQUIRED] The node's API key.")
flag.Parse()
if netName == "" {
if netName == "" || hubAddress == "" || apiKey == "" {
flag.Usage()
os.Exit(1)
}
if initURL != "" {
mainInit(initURL)
return
var err error
hubURL, err = url.Parse(hubAddress)
if err != nil {
log.Fatalf("Failed to parse hub address: %v", err)
}
main(listenIP)
main()
}
func mainInit(initURL string) {
resp, err := http.Get(initURL)
func initPeerWithHub() {
encPubKey, encPrivKey, err := box.GenerateKey(rand.Reader)
if err != nil {
log.Fatalf("Failed to fetch data from hub: %v", err)
log.Fatalf("Failed to generate encryption keys: %v", err)
}
signPubKey, signPrivKey, err := sign.GenerateKey(rand.Reader)
if err != nil {
log.Fatalf("Failed to generate signing keys: %v", err)
}
initURL := *hubURL
initURL.Path = "/peer/init/"
args := m.PeerInitArgs{
EncPubKey: encPubKey[:],
PubSignKey: signPubKey[:],
}
buf := &bytes.Buffer{}
if err := json.NewEncoder(buf).Encode(args); err != nil {
log.Fatalf("Failed to encode init args: %v", err)
}
req, err := http.NewRequest(http.MethodPost, initURL.String(), buf)
if err != nil {
log.Fatalf("Failed to construct request: %v", err)
}
req.SetBasicAuth("", apiKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatalf("Failed to init with hub: %v", err)
}
defer resp.Body.Close()
@@ -59,11 +93,16 @@ func mainInit(initURL string) {
log.Fatalf("Failed to read response body: %v", err)
}
peerConfig := m.PeerConfig{}
if err := json.Unmarshal(data, &peerConfig); err != nil {
log.Fatalf("Failed to parse configuration: %v", err)
peerConfig := localConfig{}
if err := json.Unmarshal(data, &peerConfig.PeerConfig); err != nil {
log.Fatalf("Failed to parse configuration: %v\n%s", err, data)
}
peerConfig.PubKey = encPubKey[:]
peerConfig.PrivKey = encPrivKey[:]
peerConfig.PubSignKey = signPubKey[:]
peerConfig.PrivSignKey = signPrivKey[:]
if err := storePeerConfig(netName, peerConfig); err != nil {
log.Fatalf("Failed to store configuration: %v", err)
}
@@ -73,10 +112,17 @@ func mainInit(initURL string) {
// ----------------------------------------------------------------------------
func main(listenIP string) {
func main() {
config, err := loadPeerConfig(netName)
if err != nil {
log.Fatalf("Failed to load configuration: %v", err)
log.Printf("Failed to load configuration: %v", err)
log.Printf("Initializing...")
initPeerWithHub()
config, err = loadPeerConfig(netName)
if err != nil {
log.Fatalf("Failed to load configuration: %v", err)
}
}
iface, err := openInterface(config.Network, config.PeerIP, netName)
@@ -84,7 +130,7 @@ func main(listenIP string) {
log.Fatalf("Failed to open interface: %v", err)
}
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", listenIP, config.Port))
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", config.Port))
if err != nil {
log.Fatalf("Failed to resolve UDP address: %v", err)
}
@@ -137,7 +183,7 @@ func main(listenIP string) {
}
}()
go newHubPoller(config).Run()
go newHubPoller().Run()
go readFromConn(conn)
readFromIFace(iface)
}
@@ -258,7 +304,7 @@ func handleDataPacket(h header, data []byte, decBuf []byte) {
destRoute := routingTable[h.DestIP].Load()
if !destRoute.Up {
log.Printf("Not connected (relay): %v", destRoute)
log.Printf("Not connected (relay): %d", destRoute.IP)
return
}

View File

@@ -214,7 +214,7 @@ func (s *peerSupervisor) server() stateFunc {
s.sendControlPacketTo(probePacket{TraceID: msg.Packet.TraceID}, msg.SrcAddr)
case pingTimerMsg:
if time.Since(lastSeen) > timeoutInterval {
if time.Since(lastSeen) > timeoutInterval && s.staged.Up {
logf("Connection timeout")
s.staged.Up = false
s.publish()