Audit changes.
This commit is contained in:
@@ -65,12 +65,8 @@ func (a *API) ensurePassword() error {
|
|||||||
return db.Config_Insert(a.db, conf)
|
return db.Config_Insert(a.db, conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Config_Get() *Config {
|
func (a *API) Config_Get() (*Config, error) {
|
||||||
conf, err := db.Config_Get(a.db, 1)
|
return db.Config_Get(a.db, 1)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return conf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Config_Update(conf *Config) error {
|
func (a *API) Config_Update(conf *Config) error {
|
||||||
@@ -116,7 +112,10 @@ func (a *API) session_Create() *Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Session_SignIn(s *Session, pwd string) error {
|
func (a *API) Session_SignIn(s *Session, pwd string) error {
|
||||||
conf := a.Config_Get()
|
conf, err := a.Config_Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := bcrypt.CompareHashAndPassword(conf.Password, []byte(pwd)); err != nil {
|
if err := bcrypt.CompareHashAndPassword(conf.Password, []byte(pwd)); err != nil {
|
||||||
return ErrNotAuthorized
|
return ErrNotAuthorized
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidIP = errors.New("invalid IP")
|
ErrInvalidIP = errors.New("invalid IP")
|
||||||
|
ErrInvalidPeerIP = errors.New("invalid peer IP")
|
||||||
ErrNonPrivateIP = errors.New("non-private IP")
|
ErrNonPrivateIP = errors.New("non-private IP")
|
||||||
ErrInvalidPort = errors.New("invalid port")
|
ErrInvalidPort = errors.New("invalid port")
|
||||||
ErrInvalidNetName = errors.New("invalid network name")
|
ErrInvalidNetName = errors.New("invalid network name")
|
||||||
@@ -67,7 +68,8 @@ func Peer_Sanitize(p *Peer) {
|
|||||||
p.Name = strings.TrimSpace(p.Name)
|
p.Name = strings.TrimSpace(p.Name)
|
||||||
if len(p.Addr4) != 0 {
|
if len(p.Addr4) != 0 {
|
||||||
if addr, ok := netip.AddrFromSlice(p.Addr4); ok {
|
if addr, ok := netip.AddrFromSlice(p.Addr4); ok {
|
||||||
p.Addr4 = addr.AsSlice()
|
// Unmap so an IPv4-mapped form is stored canonically as 4 bytes.
|
||||||
|
p.Addr4 = addr.Unmap().AsSlice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(p.Addr6) != 0 {
|
if len(p.Addr6) != 0 {
|
||||||
@@ -81,13 +83,18 @@ func Peer_Sanitize(p *Peer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Peer_Validate(p *Peer) error {
|
func Peer_Validate(p *Peer) error {
|
||||||
|
if p.PeerIP < 1 || p.PeerIP > 254 {
|
||||||
|
return ErrInvalidPeerIP
|
||||||
|
}
|
||||||
if len(p.Addr4) > 0 {
|
if len(p.Addr4) > 0 {
|
||||||
if _, ok := netip.AddrFromSlice(p.Addr4); !ok {
|
// Must be a genuine IPv4 address (reject an IPv6 in the v4 field).
|
||||||
|
if addr, ok := netip.AddrFromSlice(p.Addr4); !ok || !addr.Is4() {
|
||||||
return ErrInvalidIP
|
return ErrInvalidIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(p.Addr6) > 0 {
|
if len(p.Addr6) > 0 {
|
||||||
if _, ok := netip.AddrFromSlice(p.Addr6); !ok {
|
// Must be a genuine IPv6 address (reject IPv4 / IPv4-mapped in the v6 field).
|
||||||
|
if addr, ok := netip.AddrFromSlice(p.Addr6); !ok || !addr.Is6() || addr.Is4In6() {
|
||||||
return ErrInvalidIP
|
return ErrInvalidIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotAuthorized = errors.New("not authorized")
|
ErrNotAuthorized = errors.New("not authorized")
|
||||||
ErrNoIPAvailable = errors.New("no IP address available")
|
|
||||||
ErrInvalidIP = db.ErrInvalidIP
|
ErrInvalidIP = db.ErrInvalidIP
|
||||||
ErrInvalidPort = db.ErrInvalidPort
|
ErrInvalidPort = db.ErrInvalidPort
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ CREATE TABLE peers (
|
|||||||
PeerIP INTEGER NOT NULL, -- Final byte of IP.
|
PeerIP INTEGER NOT NULL, -- Final byte of IP.
|
||||||
Version INTEGER NOT NULL, -- Changes when updated.
|
Version INTEGER NOT NULL, -- Changes when updated.
|
||||||
APIKey TEXT NOT NULL UNIQUE, -- Peer's secret API key.
|
APIKey TEXT NOT NULL UNIQUE, -- Peer's secret API key.
|
||||||
Name TEXT NOT NULL UNIQUE, -- For humans.
|
Name TEXT NOT NULL, -- For humans.
|
||||||
Addr4 BLOB NOT NULL,
|
Addr4 BLOB NOT NULL,
|
||||||
Addr6 BLOB NOT NULL,
|
Addr6 BLOB NOT NULL,
|
||||||
Port INTEGER NOT NULL,
|
Port INTEGER NOT NULL,
|
||||||
Relay INTEGER NOT NULL DEFAULT 0, -- Boolean if peer will forward packets.
|
Relay INTEGER NOT NULL DEFAULT 0, -- Boolean if peer will forward packets.
|
||||||
WGPubKey BLOB NOT NULL,
|
WGPubKey BLOB NOT NULL,
|
||||||
SignPubKey BLOB NOT NULL,
|
SignPubKey BLOB NOT NULL,
|
||||||
|
UNIQUE(NetworkID, Name),
|
||||||
PRIMARY KEY(NetworkID, PeerIP)
|
PRIMARY KEY(NetworkID, PeerIP)
|
||||||
) WITHOUT ROWID;
|
) WITHOUT ROWID;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package hub
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) getCookie(r *http.Request, name string) string {
|
func (a *App) getCookie(r *http.Request, name string) string {
|
||||||
@@ -26,9 +25,12 @@ func (a *App) setCookie(w http.ResponseWriter, name, value string) {
|
|||||||
|
|
||||||
func (a *App) deleteCookie(w http.ResponseWriter, name string) {
|
func (a *App) deleteCookie(w http.ResponseWriter, name string) {
|
||||||
http.SetCookie(w, &http.Cookie{
|
http.SetCookie(w, &http.Cookie{
|
||||||
Name: name,
|
Name: name,
|
||||||
Value: "",
|
Value: "",
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Expires: time.Unix(0, 0),
|
Secure: !a.insecure,
|
||||||
|
SameSite: http.SameSiteStrictMode,
|
||||||
|
HttpOnly: true,
|
||||||
|
MaxAge: -1, // delete now
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,13 +260,17 @@ func (a *App) _adminPasswordEdit(s *api.Session, w http.ResponseWriter, r *http.
|
|||||||
|
|
||||||
func (a *App) _adminPasswordSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _adminPasswordSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
var (
|
var (
|
||||||
conf = a.api.Config_Get()
|
|
||||||
curPwd string
|
curPwd string
|
||||||
newPwd string
|
newPwd string
|
||||||
newPwd2 string
|
newPwd2 string
|
||||||
)
|
)
|
||||||
|
|
||||||
err := webutil.NewFormScanner(r.Form).
|
conf, err := a.api.Config_Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = webutil.NewFormScanner(r.Form).
|
||||||
Scan("CurrentPassword", &curPwd).
|
Scan("CurrentPassword", &curPwd).
|
||||||
Scan("NewPassword", &newPwd).
|
Scan("NewPassword", &newPwd).
|
||||||
Scan("NewPassword2", &newPwd2).
|
Scan("NewPassword2", &newPwd2).
|
||||||
@@ -337,7 +341,7 @@ func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request)
|
|||||||
LocalDomain: net.LocalDomain,
|
LocalDomain: net.LocalDomain,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.NetworkState.Peers, err = a.peersArray(net.NetworkID)
|
resp.NetworkState.Peers, err = a.peersList(net.NetworkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -346,22 +350,24 @@ func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _peerFetchState(peer *api.Peer, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _peerFetchState(peer *api.Peer, w http.ResponseWriter, r *http.Request) error {
|
||||||
peers, err := a.peersArray(peer.NetworkID)
|
peers, err := a.peersList(peer.NetworkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return a.sendJSON(w, m.NetworkState{Peers: peers})
|
return a.sendJSON(w, m.NetworkState{Peers: peers})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) peersArray(networkID int64) (peers [256]*m.Peer, err error) {
|
func (a *App) peersList(networkID int64) (peers []m.Peer, err error) {
|
||||||
l, err := a.api.Peer_List(networkID)
|
l, err := a.api.Peer_List(networkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return peers, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peers = make([]m.Peer, 0, len(l))
|
||||||
|
|
||||||
for _, p := range l {
|
for _, p := range l {
|
||||||
if len(p.WGPubKey) != 0 {
|
if len(p.WGPubKey) != 0 {
|
||||||
peers[p.PeerIP] = &m.Peer{
|
peers = append(peers, m.Peer{
|
||||||
PeerIP: p.PeerIP,
|
PeerIP: p.PeerIP,
|
||||||
Version: p.Version,
|
Version: p.Version,
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
@@ -371,9 +377,9 @@ func (a *App) peersArray(networkID int64) (peers [256]*m.Peer, err error) {
|
|||||||
Relay: p.Relay,
|
Relay: p.Relay,
|
||||||
WGPubKey: p.WGPubKey,
|
WGPubKey: p.WGPubKey,
|
||||||
SignPubKey: p.SignPubKey,
|
SignPubKey: p.SignPubKey,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return peers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,5 +26,5 @@ type Peer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NetworkState struct {
|
type NetworkState struct {
|
||||||
Peers [256]*Peer
|
Peers []Peer
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,5 @@ func (a *App) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) onShutdown() error {
|
func (a *App) onShutdown() error {
|
||||||
// TODO: removeHosts() ?
|
|
||||||
return wginterface.Delete(a.dev.Name())
|
return wginterface.Delete(a.dev.Name())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,3 +59,7 @@ func (c *udpControlConn) run(ch chan<- PingEvent) {
|
|||||||
ch <- PingEvent{srcVPNIP: srcIP.Unmap(), ping: ping}
|
ch <- PingEvent{srcVPNIP: srcIP.Unmap(), ping: ping}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *udpControlConn) Close() error {
|
||||||
|
return c.conn.Close()
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// devRetry calls fn up to 6 times with exponential backoff, retrying on EBUSY
|
// devRetry calls fn up to 6 times with exponential backoff, retrying on EBUSY
|
||||||
// (transient netlink contention during WireGuard handshake/rekey). Fatal on any other error.
|
// (transient netlink contention during WireGuard handshake/rekey). Fatal on
|
||||||
|
// any other error.
|
||||||
func devRetry(vpnIP netip.Addr, op string, fn func() error) {
|
func devRetry(vpnIP netip.Addr, op string, fn func() error) {
|
||||||
const attempts = 6
|
const attempts = 6
|
||||||
timeout := 10 * time.Millisecond
|
timeout := 10 * time.Millisecond
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ func updateHosts(hostsPath, localDomain string, peers map[netip.Addr]*Peer) erro
|
|||||||
after := ""
|
after := ""
|
||||||
|
|
||||||
if idxBegin := strings.Index(data, begin); idxBegin != -1 {
|
if idxBegin := strings.Index(data, begin); idxBegin != -1 {
|
||||||
idxEnd := strings.Index(data, end)
|
idxEnd := strings.Index(data[idxBegin:], end)
|
||||||
if idxEnd != -1 {
|
if idxEnd != -1 {
|
||||||
after = strings.TrimSpace(data[idxEnd+len(end):])
|
after = strings.TrimSpace(data[idxBegin+idxEnd+len(end):])
|
||||||
}
|
}
|
||||||
before = strings.TrimSpace(data[:idxBegin])
|
before = strings.TrimSpace(data[:idxBegin])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ func (hp *HubPoller) apply(state m.NetworkState) (changed bool) {
|
|||||||
netAddr := hp.vpnNet.Addr().As4()
|
netAddr := hp.vpnNet.Addr().As4()
|
||||||
|
|
||||||
for _, p := range state.Peers {
|
for _, p := range state.Peers {
|
||||||
if p == nil || len(p.WGPubKey) != wgtypes.KeyLen || len(p.SignPubKey) != 32 {
|
if len(p.WGPubKey) != wgtypes.KeyLen || len(p.SignPubKey) != 32 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,16 +156,17 @@ func (hp *HubPoller) apply(state m.NetworkState) (changed bool) {
|
|||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
|
|
||||||
func hubPeerFrom(pubKey wgtypes.Key, vpnIP netip.Addr, p *m.Peer) HubPeer {
|
func hubPeerFrom(pubKey wgtypes.Key, vpnIP netip.Addr, p m.Peer) HubPeer {
|
||||||
var ep4, ep6 netip.AddrPort
|
var ep4, ep6 netip.AddrPort
|
||||||
if len(p.Addr4) > 0 {
|
if len(p.Addr4) > 0 {
|
||||||
if addr, ok := netip.AddrFromSlice(p.Addr4); ok {
|
if addr, ok := netip.AddrFromSlice(p.Addr4); ok {
|
||||||
ep4 = netip.AddrPortFrom(addr.Unmap(), p.Port)
|
ep4 = netip.AddrPortFrom(addr.Unmap(), p.Port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.Addr6) > 0 {
|
if len(p.Addr6) > 0 {
|
||||||
if addr, ok := netip.AddrFromSlice(p.Addr6); ok {
|
if addr, ok := netip.AddrFromSlice(p.Addr6); ok {
|
||||||
ep6 = netip.AddrPortFrom(addr, p.Port)
|
ep6 = netip.AddrPortFrom(addr.Unmap(), p.Port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var signPubKey [32]byte
|
var signPubKey [32]byte
|
||||||
|
|||||||
@@ -24,14 +24,12 @@ func testPoller(t *testing.T) (*HubPoller, chan HubPeer, chan wgtypes.Key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func stateWith(key wgtypes.Key, peerIP byte, version int64) m.NetworkState {
|
func stateWith(key wgtypes.Key, peerIP byte, version int64) m.NetworkState {
|
||||||
var s m.NetworkState
|
return m.NetworkState{Peers: []m.Peer{{
|
||||||
s.Peers[peerIP] = &m.Peer{
|
|
||||||
PeerIP: peerIP,
|
PeerIP: peerIP,
|
||||||
Version: version,
|
Version: version,
|
||||||
WGPubKey: key[:],
|
WGPubKey: key[:],
|
||||||
SignPubKey: make([]byte, 32),
|
SignPubKey: make([]byte, 32),
|
||||||
}
|
}}}
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApply_EmitsAddsAndReportsChange(t *testing.T) {
|
func TestApply_EmitsAddsAndReportsChange(t *testing.T) {
|
||||||
|
|||||||
35
peer/init.go
35
peer/init.go
@@ -115,13 +115,34 @@ func initFromHub(hubURL, apiKey string, privKey wgtypes.Key) (LocalState, error)
|
|||||||
vpnIP := netip.AddrFrom4(octets)
|
vpnIP := netip.AddrFrom4(octets)
|
||||||
vpnNet := netip.PrefixFrom(netAddr, 24)
|
vpnNet := netip.PrefixFrom(netAddr, 24)
|
||||||
|
|
||||||
var isRelay, isPublic bool
|
var self *m.Peer
|
||||||
var wgPort uint16
|
for i := range r.NetworkState.Peers {
|
||||||
if self := r.NetworkState.Peers[r.PeerIP]; self != nil {
|
if r.NetworkState.Peers[i].PeerIP == r.PeerIP {
|
||||||
isRelay = self.Relay
|
self = &r.NetworkState.Peers[i]
|
||||||
isPublic = len(self.Addr4) > 0 || len(self.Addr6) > 0
|
break
|
||||||
wgPort = self.Port
|
}
|
||||||
}
|
}
|
||||||
|
if self == nil {
|
||||||
|
return LocalState{}, fmt.Errorf("hub init: no peer for own IP: %d", r.PeerIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
var isRelay, public bool
|
||||||
|
var wgPort uint16
|
||||||
|
|
||||||
|
var ep4, ep6 netip.AddrPort
|
||||||
|
if len(self.Addr4) > 0 {
|
||||||
|
if addr, ok := netip.AddrFromSlice(self.Addr4); ok {
|
||||||
|
ep4 = netip.AddrPortFrom(addr.Unmap(), self.Port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(self.Addr6) > 0 {
|
||||||
|
if addr, ok := netip.AddrFromSlice(self.Addr6); ok {
|
||||||
|
ep6 = netip.AddrPortFrom(addr.Unmap(), self.Port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public = ep4.IsValid() || ep6.IsValid()
|
||||||
|
isRelay = self.Relay && public
|
||||||
|
wgPort = self.Port
|
||||||
|
|
||||||
return LocalState{
|
return LocalState{
|
||||||
PrivKey: privKey,
|
PrivKey: privKey,
|
||||||
@@ -130,7 +151,7 @@ func initFromHub(hubURL, apiKey string, privKey wgtypes.Key) (LocalState, error)
|
|||||||
VPNNet: vpnNet,
|
VPNNet: vpnNet,
|
||||||
WGPort: wgPort,
|
WGPort: wgPort,
|
||||||
IsRelay: isRelay,
|
IsRelay: isRelay,
|
||||||
IsPublic: isPublic,
|
IsPublic: public,
|
||||||
LocalDomain: r.LocalDomain,
|
LocalDomain: r.LocalDomain,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,19 @@ var mcAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom(
|
|||||||
// RunMCWriter broadcasts a signed beacon on the local multicast group every
|
// RunMCWriter broadcasts a signed beacon on the local multicast group every
|
||||||
// mcBroadcastInterval so that LAN peers can discover our WireGuard endpoint.
|
// mcBroadcastInterval so that LAN peers can discover our WireGuard endpoint.
|
||||||
func RunMCWriter(selfVPNIP netip.Addr, pubKey wgtypes.Key, wgPort uint16, signKey *[64]byte) {
|
func RunMCWriter(selfVPNIP netip.Addr, pubKey wgtypes.Key, wgPort uint16, signKey *[64]byte) {
|
||||||
|
for {
|
||||||
|
runMCWriterInner(selfVPNIP, pubKey, wgPort, signKey)
|
||||||
|
time.Sleep(mcErrorRetryInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runMCWriterInner(selfVPNIP netip.Addr, pubKey wgtypes.Key, wgPort uint16, signKey *[64]byte) {
|
||||||
conn, err := net.ListenMulticastUDP("udp", nil, mcAddr)
|
conn, err := net.ListenMulticastUDP("udp", nil, mcAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[MCWriter] bind: %v", err)
|
log.Printf("[MCWriter] bind: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
payload := buildBeacon(selfVPNIP, pubKey, wgPort)
|
payload := buildBeacon(selfVPNIP, pubKey, wgPort)
|
||||||
signed := sign.Sign(nil, payload, signKey)
|
signed := sign.Sign(nil, payload, signKey)
|
||||||
@@ -38,9 +46,11 @@ func RunMCWriter(selfVPNIP netip.Addr, pubKey wgtypes.Key, wgPort uint16, signKe
|
|||||||
if _, err := conn.WriteToUDP(signed, mcAddr); err != nil {
|
if _, err := conn.WriteToUDP(signed, mcAddr); err != nil {
|
||||||
log.Printf("[MCWriter] write: %v", err)
|
log.Printf("[MCWriter] write: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for range time.Tick(mcBroadcastInterval) {
|
for range time.Tick(mcBroadcastInterval) {
|
||||||
if _, err := conn.WriteToUDP(signed, mcAddr); err != nil {
|
if _, err := conn.WriteToUDP(signed, mcAddr); err != nil {
|
||||||
log.Printf("[MCWriter] write: %v", err)
|
log.Printf("[MCWriter] write: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,26 +11,27 @@ import (
|
|||||||
func TestNetworkState_RoundTrip(t *testing.T) {
|
func TestNetworkState_RoundTrip(t *testing.T) {
|
||||||
path := filepath.Join(t.TempDir(), "network.json")
|
path := filepath.Join(t.TempDir(), "network.json")
|
||||||
|
|
||||||
var state m.NetworkState
|
state := m.NetworkState{Peers: []m.Peer{
|
||||||
state.Peers[1] = &m.Peer{
|
{
|
||||||
PeerIP: 1,
|
PeerIP: 1,
|
||||||
Version: 7,
|
Version: 7,
|
||||||
Name: "hub",
|
Name: "hub",
|
||||||
Addr4: []byte{10, 11, 12, 1},
|
Addr4: []byte{10, 11, 12, 1},
|
||||||
Port: 51820,
|
Port: 51820,
|
||||||
Relay: true,
|
Relay: true,
|
||||||
WGPubKey: make([]byte, 32),
|
WGPubKey: make([]byte, 32),
|
||||||
SignPubKey: make([]byte, 32),
|
SignPubKey: make([]byte, 32),
|
||||||
}
|
},
|
||||||
state.Peers[10] = &m.Peer{
|
{
|
||||||
PeerIP: 10,
|
PeerIP: 10,
|
||||||
Version: 3,
|
Version: 3,
|
||||||
Name: "laptop",
|
Name: "laptop",
|
||||||
Addr4: []byte{10, 11, 12, 10},
|
Addr4: []byte{10, 11, 12, 10},
|
||||||
Port: 51820,
|
Port: 51820,
|
||||||
WGPubKey: []byte("0123456789abcdef0123456789abcdef"),
|
WGPubKey: []byte("0123456789abcdef0123456789abcdef"),
|
||||||
SignPubKey: []byte("fedcba9876543210fedcba9876543210"),
|
SignPubKey: []byte("fedcba9876543210fedcba9876543210"),
|
||||||
}
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
if err := saveNetworkState(path, state); err != nil {
|
if err := saveNetworkState(path, state); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
25
peer/new.go
25
peer/new.go
@@ -27,24 +27,35 @@ func New(
|
|||||||
|
|
||||||
dev, err := wginterface.Open(ifaceName)
|
dev, err := wginterface.Open(ifaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
_ = wginterface.Delete(ifaceName)
|
||||||
return nil, fmt.Errorf("open WG device: %w", err)
|
return nil, fmt.Errorf("open WG device: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc, err := newUDPControlConn(state.VPNIP, ControlPort)
|
||||||
|
if err != nil {
|
||||||
|
_ = dev.Close()
|
||||||
|
_ = wginterface.Delete(ifaceName)
|
||||||
|
return nil, fmt.Errorf("control conn: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup := func() {
|
||||||
|
_ = cc.Close()
|
||||||
|
_ = dev.Close()
|
||||||
|
_ = wginterface.Delete(ifaceName)
|
||||||
|
}
|
||||||
|
|
||||||
if err := dev.Configure(state.PrivKey, int(state.WGPort)); err != nil {
|
if err := dev.Configure(state.PrivKey, int(state.WGPort)); err != nil {
|
||||||
|
cleanup()
|
||||||
return nil, fmt.Errorf("configure WG device: %w", err)
|
return nil, fmt.Errorf("configure WG device: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.IsRelay {
|
if state.IsRelay {
|
||||||
if err := dev.EnableForwarding(); err != nil {
|
if err := dev.EnableForwarding(); err != nil {
|
||||||
|
cleanup()
|
||||||
return nil, fmt.Errorf("enable forwarding: %w", err)
|
return nil, fmt.Errorf("enable forwarding: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, err := newUDPControlConn(state.VPNIP, ControlPort)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("control conn: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pingCh := make(chan PingEvent)
|
pingCh := make(chan PingEvent)
|
||||||
hubAddCh := make(chan HubPeer)
|
hubAddCh := make(chan HubPeer)
|
||||||
hubRemoveCh := make(chan wgtypes.Key)
|
hubRemoveCh := make(chan wgtypes.Key)
|
||||||
@@ -59,13 +70,15 @@ func New(
|
|||||||
hubAddCh,
|
hubAddCh,
|
||||||
hubRemoveCh)
|
hubRemoveCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
return nil, fmt.Errorf("hub poller: %w", err)
|
return nil, fmt.Errorf("hub poller: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go cc.run(pingCh)
|
go cc.run(pingCh)
|
||||||
go poller.Run()
|
go poller.Run()
|
||||||
go RunMCWriter(state.VPNIP, state.PrivKey.PublicKey(), state.WGPort, &state.SignKey)
|
|
||||||
if !state.IsPublic {
|
if !state.IsPublic {
|
||||||
|
go RunMCWriter(state.VPNIP, state.PrivKey.PublicKey(), state.WGPort, &state.SignKey)
|
||||||
go RunMCReader(state.VPNNet, state.VPNIP, multicastCh)
|
go RunMCReader(state.VPNNet, state.VPNIP, multicastCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user