WIP
This commit is contained in:
parent
03b1bbcbcf
commit
d558ebbd14
14
README.md
14
README.md
@ -38,6 +38,7 @@ Add and start the hub server:
|
|||||||
|
|
||||||
```
|
```
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
systemctl enable hub
|
||||||
systemctl start hub
|
systemctl start hub
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -62,10 +63,19 @@ AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
|
|||||||
Type=simple
|
Type=simple
|
||||||
User=user
|
User=user
|
||||||
WorkingDirectory=/home/user/
|
WorkingDirectory=/home/user/
|
||||||
ExecStart=/home/user/vppn -name vppn -hub-address https://my.hub -api-key 1234567890
|
ExecStart=/home/user/vppn -hub-address https://my.hub -api-key 1234567890
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=8
|
RestartSec=8
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
Add and start the service:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable vppn
|
||||||
|
systemctl start vppn
|
||||||
```
|
```
|
||||||
|
10
go.mod
10
go.mod
@ -3,13 +3,13 @@ module vppn
|
|||||||
go 1.24.1
|
go 1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.crumpington.com/lib/go v0.8.1
|
git.crumpington.com/lib/go v0.9.0
|
||||||
golang.org/x/crypto v0.29.0
|
golang.org/x/crypto v0.36.0
|
||||||
golang.org/x/sys v0.27.0
|
golang.org/x/sys v0.31.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||||
golang.org/x/net v0.31.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/text v0.20.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
)
|
)
|
||||||
|
20
go.sum
20
go.sum
@ -1,12 +1,12 @@
|
|||||||
git.crumpington.com/lib/go v0.8.1 h1:rWjddllSxQ4yReraqDaGZAod4NpRD9LtGx1yV71ytcU=
|
git.crumpington.com/lib/go v0.9.0 h1:QXoMhsycSgEUWNiiPZWl0jgBls+NI9TNR5Z6nNXslCM=
|
||||||
git.crumpington.com/lib/go v0.8.1/go.mod h1:XjQaf2NFlje9BJ1EevZL8NNioPrAe7WwHpKUhcDw2Lk=
|
git.crumpington.com/lib/go v0.9.0/go.mod h1:i3DXiPDo/pgPMHAxUTpyo1Xj2spcvXwXcBef3aSYlnQ=
|
||||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
|
@ -54,17 +54,11 @@ func (a *API) ensurePassword() error {
|
|||||||
log.Printf("Setting password: %s", pwd)
|
log.Printf("Setting password: %s", pwd)
|
||||||
|
|
||||||
hashed, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
|
hashed, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := &Config{
|
conf := &Config{ConfigID: 1, Password: hashed}
|
||||||
ConfigID: 1,
|
|
||||||
VPNNetwork: []byte{10, 1, 1, 0},
|
|
||||||
Password: hashed,
|
|
||||||
}
|
|
||||||
|
|
||||||
return db.Config_Insert(a.db, conf)
|
return db.Config_Insert(a.db, conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,10 +74,6 @@ func (a *API) Config_Update(conf *Config) error {
|
|||||||
return db.Config_Update(a.db, conf)
|
return db.Config_Update(a.db, conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Config_UpdatePassword(pwdHash []byte) error {
|
|
||||||
return db.Config_UpdatePassword(a.db, pwdHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) Session_Delete(sessionID string) error {
|
func (a *API) Session_Delete(sessionID string) error {
|
||||||
return db.Session_Delete(a.db, sessionID)
|
return db.Session_Delete(a.db, sessionID)
|
||||||
}
|
}
|
||||||
@ -137,6 +127,24 @@ func (a *API) Session_SignIn(s *Session, pwd string) error {
|
|||||||
return db.Session_SetSignedIn(a.db, s.SessionID)
|
return db.Session_SetSignedIn(a.db, s.SessionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) Network_Create(n *Network) error {
|
||||||
|
n.NetworkID = idgen.NextID(0)
|
||||||
|
return db.Network_Insert(a.db, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) Network_Delete(n *Network) error {
|
||||||
|
return db.Network_Delete(a.db, n.NetworkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) Network_Get(id int64) (*Network, error) {
|
||||||
|
return db.Network_Get(a.db, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) Network_List() ([]*Network, error) {
|
||||||
|
const query = db.Network_SelectQuery + ` ORDER BY Name ASC`
|
||||||
|
return db.Network_List(a.db, query)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) Peer_CreateNew(p *Peer) error {
|
func (a *API) Peer_CreateNew(p *Peer) error {
|
||||||
p.Version = idgen.NextID(0)
|
p.Version = idgen.NextID(0)
|
||||||
p.PubKey = []byte{}
|
p.PubKey = []byte{}
|
||||||
@ -146,7 +154,7 @@ func (a *API) Peer_CreateNew(p *Peer) error {
|
|||||||
return db.Peer_Insert(a.db, p)
|
return db.Peer_Insert(a.db, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Peer_Init(peer *Peer, args m.PeerInitArgs) (*m.PeerConfig, error) {
|
func (a *API) Peer_Init(peer *Peer, args m.PeerInitArgs) error {
|
||||||
a.lock.Lock()
|
a.lock.Lock()
|
||||||
defer a.lock.Unlock()
|
defer a.lock.Unlock()
|
||||||
|
|
||||||
@ -154,19 +162,7 @@ func (a *API) Peer_Init(peer *Peer, args m.PeerInitArgs) (*m.PeerConfig, error)
|
|||||||
peer.PubKey = args.EncPubKey
|
peer.PubKey = args.EncPubKey
|
||||||
peer.PubSignKey = args.PubSignKey
|
peer.PubSignKey = args.PubSignKey
|
||||||
|
|
||||||
if err := db.Peer_UpdateFull(a.db, peer); err != nil {
|
return db.Peer_UpdateFull(a.db, peer)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
conf := a.Config_Get()
|
|
||||||
|
|
||||||
return &m.PeerConfig{
|
|
||||||
PeerIP: peer.PeerIP,
|
|
||||||
Network: conf.VPNNetwork,
|
|
||||||
PublicIP: peer.PublicIP,
|
|
||||||
Port: peer.Port,
|
|
||||||
Relay: peer.Relay,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Peer_Update(p *Peer) error {
|
func (a *API) Peer_Update(p *Peer) error {
|
||||||
@ -177,16 +173,16 @@ func (a *API) Peer_Update(p *Peer) error {
|
|||||||
return db.Peer_Update(a.db, p)
|
return db.Peer_Update(a.db, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Peer_Delete(ip byte) error {
|
func (a *API) Peer_Delete(networkID int64, peerIP byte) error {
|
||||||
return db.Peer_Delete(a.db, ip)
|
return db.Peer_Delete(a.db, networkID, peerIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Peer_List() ([]*Peer, error) {
|
func (a *API) Peer_List(networkID int64) ([]*Peer, error) {
|
||||||
return db.Peer_ListAll(a.db)
|
return db.Peer_ListAll(a.db, networkID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Peer_Get(ip byte) (*Peer, error) {
|
func (a *API) Peer_Get(networkID int64, ip byte) (*Peer, error) {
|
||||||
return db.Peer_Get(a.db, ip)
|
return db.Peer_Get(a.db, networkID, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) Peer_GetByAPIKey(key string) (*Peer, error) {
|
func (a *API) Peer_GetByAPIKey(key string) (*Peer, error) {
|
||||||
|
@ -17,12 +17,10 @@ type TX interface {
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ConfigID int64
|
ConfigID int64
|
||||||
HubAddress string
|
|
||||||
VPNNetwork []byte
|
|
||||||
Password []byte
|
Password []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
const Config_SelectQuery = "SELECT ConfigID,HubAddress,VPNNetwork,Password FROM config"
|
const Config_SelectQuery = "SELECT ConfigID,Password FROM config"
|
||||||
|
|
||||||
func Config_Insert(
|
func Config_Insert(
|
||||||
tx TX,
|
tx TX,
|
||||||
@ -33,7 +31,7 @@ func Config_Insert(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = tx.Exec("INSERT INTO config(ConfigID,HubAddress,VPNNetwork,Password) VALUES(?,?,?,?)", row.ConfigID, row.HubAddress, row.VPNNetwork, row.Password)
|
_, err = tx.Exec("INSERT INTO config(ConfigID,Password) VALUES(?,?)", row.ConfigID, row.Password)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +44,7 @@ func Config_Update(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec("UPDATE config SET HubAddress=?,VPNNetwork=? WHERE ConfigID=?", row.HubAddress, row.VPNNetwork, row.ConfigID)
|
result, err := tx.Exec("UPDATE config SET Password=? WHERE ConfigID=?", row.Password, row.ConfigID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -74,7 +72,7 @@ func Config_UpdateFull(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec("UPDATE config SET HubAddress=?,VPNNetwork=?,Password=? WHERE ConfigID=?", row.HubAddress, row.VPNNetwork, row.Password, row.ConfigID)
|
result, err := tx.Exec("UPDATE config SET Password=? WHERE ConfigID=?", row.Password, row.ConfigID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -124,8 +122,8 @@ func Config_Get(
|
|||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
row = &Config{}
|
row = &Config{}
|
||||||
r := tx.QueryRow("SELECT ConfigID,HubAddress,VPNNetwork,Password FROM config WHERE ConfigID=?", ConfigID)
|
r := tx.QueryRow("SELECT ConfigID,Password FROM config WHERE ConfigID=?", ConfigID)
|
||||||
err = r.Scan(&row.ConfigID, &row.HubAddress, &row.VPNNetwork, &row.Password)
|
err = r.Scan(&row.ConfigID, &row.Password)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +137,7 @@ func Config_GetWhere(
|
|||||||
) {
|
) {
|
||||||
row = &Config{}
|
row = &Config{}
|
||||||
r := tx.QueryRow(query, args...)
|
r := tx.QueryRow(query, args...)
|
||||||
err = r.Scan(&row.ConfigID, &row.HubAddress, &row.VPNNetwork, &row.Password)
|
err = r.Scan(&row.ConfigID, &row.Password)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +157,7 @@ func Config_Iterate(
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
row := &Config{}
|
row := &Config{}
|
||||||
err := rows.Scan(&row.ConfigID, &row.HubAddress, &row.VPNNetwork, &row.Password)
|
err := rows.Scan(&row.ConfigID, &row.Password)
|
||||||
if !yield(row, err) {
|
if !yield(row, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -302,11 +300,156 @@ func Session_List(
|
|||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Table: networks
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Network struct {
|
||||||
|
NetworkID int64
|
||||||
|
Name string
|
||||||
|
Network []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
const Network_SelectQuery = "SELECT NetworkID,Name,Network FROM networks"
|
||||||
|
|
||||||
|
func Network_Insert(
|
||||||
|
tx TX,
|
||||||
|
row *Network,
|
||||||
|
) (err error) {
|
||||||
|
Network_Sanitize(row)
|
||||||
|
if err = Network_Validate(row); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec("INSERT INTO networks(NetworkID,Name,Network) VALUES(?,?,?)", row.NetworkID, row.Name, row.Network)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_UpdateFull(
|
||||||
|
tx TX,
|
||||||
|
row *Network,
|
||||||
|
) (err error) {
|
||||||
|
Network_Sanitize(row)
|
||||||
|
if err = Network_Validate(row); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := tx.Exec("UPDATE networks SET Name=?,Network=? WHERE NetworkID=?", row.Name, row.Network, row.NetworkID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
return sql.ErrNoRows
|
||||||
|
case 1:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
panic("multiple rows updated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_Delete(
|
||||||
|
tx TX,
|
||||||
|
NetworkID int64,
|
||||||
|
) (err error) {
|
||||||
|
result, err := tx.Exec("DELETE FROM networks WHERE NetworkID=?", NetworkID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
switch n {
|
||||||
|
case 0:
|
||||||
|
return sql.ErrNoRows
|
||||||
|
case 1:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
panic("multiple rows deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_Get(
|
||||||
|
tx TX,
|
||||||
|
NetworkID int64,
|
||||||
|
) (
|
||||||
|
row *Network,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
row = &Network{}
|
||||||
|
r := tx.QueryRow("SELECT NetworkID,Name,Network FROM networks WHERE NetworkID=?", NetworkID)
|
||||||
|
err = r.Scan(&row.NetworkID, &row.Name, &row.Network)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_GetWhere(
|
||||||
|
tx TX,
|
||||||
|
query string,
|
||||||
|
args ...any,
|
||||||
|
) (
|
||||||
|
row *Network,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
row = &Network{}
|
||||||
|
r := tx.QueryRow(query, args...)
|
||||||
|
err = r.Scan(&row.NetworkID, &row.Name, &row.Network)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_Iterate(
|
||||||
|
tx TX,
|
||||||
|
query string,
|
||||||
|
args ...any,
|
||||||
|
) iter.Seq2[*Network, error] {
|
||||||
|
rows, err := tx.Query(query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return func(yield func(*Network, error) bool) {
|
||||||
|
yield(nil, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(yield func(*Network, error) bool) {
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
row := &Network{}
|
||||||
|
err := rows.Scan(&row.NetworkID, &row.Name, &row.Network)
|
||||||
|
if !yield(row, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_List(
|
||||||
|
tx TX,
|
||||||
|
query string,
|
||||||
|
args ...any,
|
||||||
|
) (
|
||||||
|
l []*Network,
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
for row, err := range Network_Iterate(tx, query, args...) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l = append(l, row)
|
||||||
|
}
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Table: peers
|
// Table: peers
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
|
NetworkID int64
|
||||||
PeerIP byte
|
PeerIP byte
|
||||||
Version int64
|
Version int64
|
||||||
APIKey string
|
APIKey string
|
||||||
@ -318,7 +461,7 @@ type Peer struct {
|
|||||||
PubSignKey []byte
|
PubSignKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
const Peer_SelectQuery = "SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers"
|
const Peer_SelectQuery = "SELECT NetworkID,PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers"
|
||||||
|
|
||||||
func Peer_Insert(
|
func Peer_Insert(
|
||||||
tx TX,
|
tx TX,
|
||||||
@ -329,7 +472,7 @@ func Peer_Insert(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = tx.Exec("INSERT INTO peers(PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey) VALUES(?,?,?,?,?,?,?,?,?)", row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey)
|
_, err = tx.Exec("INSERT INTO peers(NetworkID,PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey) VALUES(?,?,?,?,?,?,?,?,?,?)", row.NetworkID, row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +485,7 @@ func Peer_Update(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec("UPDATE peers SET Version=?,Name=?,PublicIP=?,Port=?,Relay=? WHERE PeerIP=?", row.Version, row.Name, row.PublicIP, row.Port, row.Relay, row.PeerIP)
|
result, err := tx.Exec("UPDATE peers SET Version=?,Name=?,PublicIP=?,Port=?,Relay=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.Name, row.PublicIP, row.Port, row.Relay, row.NetworkID, row.PeerIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -370,7 +513,7 @@ func Peer_UpdateFull(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP=?,Port=?,Relay=?,PubKey=?,PubSignKey=? WHERE PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey, row.PeerIP)
|
result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP=?,Port=?,Relay=?,PubKey=?,PubSignKey=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey, row.NetworkID, row.PeerIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -391,9 +534,10 @@ func Peer_UpdateFull(
|
|||||||
|
|
||||||
func Peer_Delete(
|
func Peer_Delete(
|
||||||
tx TX,
|
tx TX,
|
||||||
|
NetworkID int64,
|
||||||
PeerIP byte,
|
PeerIP byte,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
result, err := tx.Exec("DELETE FROM peers WHERE PeerIP=?", PeerIP)
|
result, err := tx.Exec("DELETE FROM peers WHERE NetworkID=? AND PeerIP=?", NetworkID, PeerIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -414,14 +558,15 @@ func Peer_Delete(
|
|||||||
|
|
||||||
func Peer_Get(
|
func Peer_Get(
|
||||||
tx TX,
|
tx TX,
|
||||||
|
NetworkID int64,
|
||||||
PeerIP byte,
|
PeerIP byte,
|
||||||
) (
|
) (
|
||||||
row *Peer,
|
row *Peer,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
row = &Peer{}
|
row = &Peer{}
|
||||||
r := tx.QueryRow("SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers WHERE PeerIP=?", PeerIP)
|
r := tx.QueryRow("SELECT NetworkID,PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers WHERE NetworkID=? AND PeerIP=?", NetworkID, PeerIP)
|
||||||
err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +580,7 @@ func Peer_GetWhere(
|
|||||||
) {
|
) {
|
||||||
row = &Peer{}
|
row = &Peer{}
|
||||||
r := tx.QueryRow(query, args...)
|
r := tx.QueryRow(query, args...)
|
||||||
err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +600,7 @@ func Peer_Iterate(
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
row := &Peer{}
|
row := &Peer{}
|
||||||
err := rows.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
err := rows.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey)
|
||||||
if !yield(row, err) {
|
if !yield(row, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,21 @@ package db
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrInvalidIP = errors.New("invalid IP")
|
ErrInvalidIP = errors.New("invalid IP")
|
||||||
|
ErrNonPrivateIP = errors.New("non-private IP")
|
||||||
ErrInvalidPort = errors.New("invalid port")
|
ErrInvalidPort = errors.New("invalid port")
|
||||||
|
ErrInvalidNetName = errors.New("invalid network name")
|
||||||
|
ErrInvalidPeerName = errors.New("invalid peer name")
|
||||||
)
|
)
|
||||||
|
|
||||||
func Config_Sanitize(c *Config) {
|
func Config_Sanitize(c *Config) {
|
||||||
if u, err := url.Parse(c.HubAddress); err == nil {
|
|
||||||
c.HubAddress = u.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
if addr, ok := netip.AddrFromSlice(c.VPNNetwork); ok {
|
|
||||||
c.VPNNetwork = addr.AsSlice()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Config_Validate(c *Config) error {
|
func Config_Validate(c *Config) error {
|
||||||
if _, err := url.Parse(c.HubAddress); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
addr, ok := netip.AddrFromSlice(c.VPNNetwork)
|
|
||||||
if !ok || !addr.Is4() || addr.As4()[3] != 0 || addr.As4()[0] == 0 {
|
|
||||||
return ErrInvalidIP
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +28,42 @@ func Session_Validate(s *Session) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Network_Sanitize(n *Network) {
|
||||||
|
n.Name = strings.TrimSpace(n.Name)
|
||||||
|
|
||||||
|
if addr, ok := netip.AddrFromSlice(n.Network); ok {
|
||||||
|
n.Network = addr.AsSlice()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Network_Validate(c *Network) error {
|
||||||
|
// 16 bytes is linux limit for network interface names.
|
||||||
|
if len(c.Name) == 0 || len(c.Name) > 16 {
|
||||||
|
return ErrInvalidNetName
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range c.Name {
|
||||||
|
if c >= 'a' && c <= 'z' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c >= '0' && c <= '9' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return ErrInvalidNetName
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, ok := netip.AddrFromSlice(c.Network)
|
||||||
|
if !ok || !addr.Is4() || addr.As4()[3] != 0 || addr.As4()[0] == 0 {
|
||||||
|
return ErrInvalidIP
|
||||||
|
}
|
||||||
|
|
||||||
|
if !addr.IsPrivate() {
|
||||||
|
return ErrNonPrivateIP
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func Peer_Sanitize(p *Peer) {
|
func Peer_Sanitize(p *Peer) {
|
||||||
p.Name = strings.TrimSpace(p.Name)
|
p.Name = strings.TrimSpace(p.Name)
|
||||||
if len(p.PublicIP) != 0 {
|
if len(p.PublicIP) != 0 {
|
||||||
@ -65,5 +87,20 @@ func Peer_Validate(p *Peer) error {
|
|||||||
if p.Port == 0 {
|
if p.Port == 0 {
|
||||||
return ErrInvalidPort
|
return ErrInvalidPort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, c := range p.Name {
|
||||||
|
if c >= 'a' && c <= 'z' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c >= '0' && c <= '9' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c == '.' || c == '-' || c == '_' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrInvalidPeerName
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
TABLE config OF Config (
|
TABLE config OF Config (
|
||||||
ConfigID int64 PK,
|
ConfigID int64 PK,
|
||||||
HubAddress string,
|
Password []byte
|
||||||
VPNNetwork []byte,
|
|
||||||
Password []byte NoUpdate
|
|
||||||
);
|
);
|
||||||
|
|
||||||
TABLE sessions OF Session NoUpdate (
|
TABLE sessions OF Session NoUpdate (
|
||||||
@ -13,7 +11,14 @@ TABLE sessions OF Session NoUpdate (
|
|||||||
LastSeenAt int64
|
LastSeenAt int64
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TABLE networks OF Network (
|
||||||
|
NetworkID int64 PK,
|
||||||
|
Name string NoUpdate,
|
||||||
|
Network []byte NoUpdate
|
||||||
|
);
|
||||||
|
|
||||||
TABLE peers OF Peer (
|
TABLE peers OF Peer (
|
||||||
|
NetworkID int64 PK,
|
||||||
PeerIP byte PK,
|
PeerIP byte PK,
|
||||||
Version int64,
|
Version int64,
|
||||||
APIKey string NoUpdate,
|
APIKey string NoUpdate,
|
||||||
|
@ -26,16 +26,9 @@ func Session_DeleteBefore(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Config_UpdatePassword(
|
func Peer_ListAll(tx TX, networkID int64) ([]*Peer, error) {
|
||||||
tx TX,
|
const query = Peer_SelectQuery + ` WHERE NetworkID=? ORDER BY PeerIP ASC`
|
||||||
pwdHash []byte,
|
return Peer_List(tx, query, networkID)
|
||||||
) (err error) {
|
|
||||||
_, err = tx.Exec("UPDATE config SET Password=? WHERE ConfigID=1", pwdHash)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Peer_ListAll(tx TX) ([]*Peer, error) {
|
|
||||||
return Peer_List(tx, Peer_SelectQuery)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Peer_GetByAPIKey(tx TX, apiKey string) (*Peer, error) {
|
func Peer_GetByAPIKey(tx TX, apiKey string) (*Peer, error) {
|
||||||
@ -45,7 +38,8 @@ func Peer_GetByAPIKey(tx TX, apiKey string) (*Peer, error) {
|
|||||||
apiKey)
|
apiKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Peer_Exists(tx TX, ip byte) (exists bool, err error) {
|
func Peer_Exists(tx TX, networkID int64, ip byte) (exists bool, err error) {
|
||||||
err = tx.QueryRow(`SELECT EXISTS(SELECT 1 FROM peers WHERE PeerIP=?)`, ip).Scan(&exists)
|
const query = `SELECT EXISTS(SELECT 1 FROM peers WHERE NetworkID=? AND PeerIP=?)`
|
||||||
|
err = tx.QueryRow(query, networkID, ip).Scan(&exists)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
CREATE TABLE config (
|
CREATE TABLE config (
|
||||||
ConfigID INTEGER NOT NULL PRIMARY KEY, -- Always 1.
|
ConfigID INTEGER NOT NULL PRIMARY KEY, -- Always 1.
|
||||||
HubAddress TEXT NOT NULL, -- https://for.example.com
|
|
||||||
VPNNetwork BLOB NOT NULL, -- Network (/24), example 10.51.50.0
|
|
||||||
Password BLOB NOT NULL -- bcrypt password for web interface
|
Password BLOB NOT NULL -- bcrypt password for web interface
|
||||||
) WITHOUT ROWID;
|
) WITHOUT ROWID;
|
||||||
|
|
||||||
@ -15,13 +13,22 @@ CREATE TABLE sessions (
|
|||||||
|
|
||||||
CREATE INDEX sessions_last_seen_index ON sessions(LastSeenAt);
|
CREATE INDEX sessions_last_seen_index ON sessions(LastSeenAt);
|
||||||
|
|
||||||
|
CREATE TABLE networks (
|
||||||
|
NetworkID INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
Name TEXT NOT NULL UNIQUE, -- Network/interface name.
|
||||||
|
Network BLOB NOT NULL UNIQUE -- Network (/24), example 10.51.50.0
|
||||||
|
) WITHOUT ROWID;
|
||||||
|
|
||||||
CREATE TABLE peers (
|
CREATE TABLE peers (
|
||||||
PeerIP INTEGER NOT NULL PRIMARY KEY, -- Final byte.
|
NetworkID INTEGER NOT NULL,
|
||||||
Version INTEGER NOT NULL,
|
PeerIP INTEGER NOT NULL, -- Final byte of IP.
|
||||||
APIKey TEXT NOT NULL UNIQUE,
|
Version INTEGER NOT NULL, -- Changes when updated.
|
||||||
|
APIKey TEXT NOT NULL UNIQUE, -- Peer's secret API key.
|
||||||
Name TEXT NOT NULL UNIQUE, -- For humans.
|
Name TEXT NOT NULL UNIQUE, -- For humans.
|
||||||
PublicIP BLOB NOT NULL,
|
PublicIP BLOB NOT NULL,
|
||||||
Port INTEGER NOT NULL,
|
Port INTEGER NOT NULL,
|
||||||
Relay INTEGER NOT NULL DEFAULT 0, -- Boolean if peer will forward packets. Must also have public address.
|
Relay INTEGER NOT NULL DEFAULT 0, -- Boolean if peer will forward packets. Must also have public address.
|
||||||
PubKey BLOB NOT NULL
|
PubKey BLOB NOT NULL,
|
||||||
|
PubSignKey BLOB NOT NULL,
|
||||||
|
PRIMARY KEY(NetworkID, PeerIP)
|
||||||
) WITHOUT ROWID;
|
) WITHOUT ROWID;
|
||||||
|
@ -1 +0,0 @@
|
|||||||
ALTER TABLE peers ADD COLUMN PubSignKey BLOB NOT NULL DEFAULT '';
|
|
@ -4,4 +4,5 @@ import "vppn/hub/api/db"
|
|||||||
|
|
||||||
type Config = db.Config
|
type Config = db.Config
|
||||||
type Session = db.Session
|
type Session = db.Session
|
||||||
|
type Network = db.Network
|
||||||
type Peer = db.Peer
|
type Peer = db.Peer
|
||||||
|
42
hub/form.go
Normal file
42
hub/form.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package hub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"vppn/hub/api"
|
||||||
|
|
||||||
|
"git.crumpington.com/lib/go/webutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (app *App) formGetNetwork(form url.Values) (*api.Network, error) {
|
||||||
|
var id int64
|
||||||
|
if err := webutil.NewFormScanner(form).Scan("NetworkID", &id).Error(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return app.api.Network_Get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) formGetNetworkPeers(form url.Values) (*api.Network, []*api.Peer, error) {
|
||||||
|
n, err := app.formGetNetwork(form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
peers, err := app.api.Peer_List(n.NetworkID)
|
||||||
|
return n, peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) formGetPeer(form url.Values) (*api.Network, *api.Peer, error) {
|
||||||
|
net, err := app.formGetNetwork(form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ip byte
|
||||||
|
if err := webutil.NewFormScanner(form).Scan("PeerIP", &ip).Error(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
peer, err := app.api.Peer_Get(net.NetworkID, ip)
|
||||||
|
return net, peer, err
|
||||||
|
}
|
420
hub/handlers.go
420
hub/handlers.go
@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
func (a *App) _root(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _root(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
if s.SignedIn {
|
if s.SignedIn {
|
||||||
return a.redirect(w, r, "/admin/config/")
|
return a.redirect(w, r, "/admin/network/list/")
|
||||||
} else {
|
} else {
|
||||||
return a.redirect(w, r, "/sign-in/")
|
return a.redirect(w, r, "/sign-in/")
|
||||||
}
|
}
|
||||||
@ -54,54 +54,219 @@ func (a *App) _adminSignOutSubmit(s *api.Session, w http.ResponseWriter, r *http
|
|||||||
return a.redirect(w, r, "/")
|
return a.redirect(w, r, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _adminConfig(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _adminNetworkList(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
peers, err := a.api.Peer_List()
|
l, err := a.api.Network_List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return a.render("/admin-network-list.html", w, struct {
|
||||||
return a.render("/admin-config.html", w, struct {
|
|
||||||
Session *api.Session
|
Session *api.Session
|
||||||
Peers []*api.Peer
|
Networks []*api.Network
|
||||||
Config *api.Config
|
}{s, l})
|
||||||
}{
|
|
||||||
s,
|
|
||||||
peers,
|
|
||||||
a.api.Config_Get(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _adminConfigEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _adminNetworkCreate(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
return a.render("/admin-config-edit.html", w, struct {
|
return a.render("/admin-network-create.html", w, struct{ Session *api.Session }{s})
|
||||||
Session *api.Session
|
|
||||||
Config *api.Config
|
|
||||||
}{
|
|
||||||
s,
|
|
||||||
a.api.Config_Get(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _adminConfigEditSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _adminNetworkCreateSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
var (
|
n := &api.Network{}
|
||||||
conf = a.api.Config_Get()
|
var netStr string
|
||||||
ipStr string
|
|
||||||
)
|
|
||||||
|
|
||||||
err := webutil.NewFormScanner(r.Form).
|
err := webutil.NewFormScanner(r.Form).
|
||||||
Scan("HubAddress", &conf.HubAddress).
|
Scan("Name", &n.Name).
|
||||||
Scan("VPNNetwork", &ipStr).
|
Scan("Network", &netStr).
|
||||||
Error()
|
Error()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.VPNNetwork, err = stringToIP(ipStr); err != nil {
|
n.Network, err = stringToIP(netStr)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := a.api.Config_Update(conf); err != nil {
|
|
||||||
|
if err := a.api.Network_Create(n); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return a.redirect(w, r, "/admin/config/")
|
|
||||||
|
return a.redirect(w, r, "/admin/network/view/?NetworkID=%d", n.NetworkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminNetworkView(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, peers, err := a.formGetNetworkPeers(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.render("/network/network-view.html", w, struct {
|
||||||
|
Session *api.Session
|
||||||
|
Network *api.Network
|
||||||
|
Peers []*api.Peer
|
||||||
|
}{s, n, peers})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminNetworkDelete(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, peers, err := a.formGetNetworkPeers(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.render("/network/network-delete.html", w, struct {
|
||||||
|
Session *api.Session
|
||||||
|
Network *api.Network
|
||||||
|
Peers []*api.Peer
|
||||||
|
}{s, n, peers})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminNetworkDeleteSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, err := a.formGetNetwork(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = a.api.Network_Delete(n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return a.redirect(w, r, "/admin/network/list/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerCreate(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, err := a.formGetNetwork(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.render("/network/peer-create.html", w, struct {
|
||||||
|
Session *api.Session
|
||||||
|
Network *api.Network
|
||||||
|
}{s, n})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerCreateSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
var ipStr string
|
||||||
|
|
||||||
|
p := &api.Peer{}
|
||||||
|
err := webutil.NewFormScanner(r.Form).
|
||||||
|
Scan("NetworkID", &p.NetworkID).
|
||||||
|
Scan("IP", &p.PeerIP).
|
||||||
|
Scan("Name", &p.Name).
|
||||||
|
Scan("PublicIP", &ipStr).
|
||||||
|
Scan("Port", &p.Port).
|
||||||
|
Scan("Relay", &p.Relay).
|
||||||
|
Error()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.PublicIP, err = stringToIP(ipStr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.api.Peer_CreateNew(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return a.redirect(w, r, "/admin/peer/view/?NetworkID=%d&PeerIP=%d", p.NetworkID, p.PeerIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerView(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
net, peer, err := a.formGetPeer(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.render("/network/peer-view.html", w, struct {
|
||||||
|
Session *api.Session
|
||||||
|
Network *api.Network
|
||||||
|
Peer *api.Peer
|
||||||
|
}{s, net, peer})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
net, peer, err := a.formGetPeer(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.render("/network/peer-edit.html", w, struct {
|
||||||
|
Session *api.Session
|
||||||
|
Network *api.Network
|
||||||
|
Peer *api.Peer
|
||||||
|
}{s, net, peer})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerEditSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
_, peer, err := a.formGetPeer(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipStr string
|
||||||
|
|
||||||
|
err = webutil.NewFormScanner(r.Form).
|
||||||
|
Scan("Name", &peer.Name).
|
||||||
|
Scan("PublicIP", &ipStr).
|
||||||
|
Scan("Port", &peer.Port).
|
||||||
|
Scan("Relay", &peer.Relay).
|
||||||
|
Error()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if peer.PublicIP, err = stringToIP(ipStr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = a.api.Peer_Update(peer); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.redirect(w, r, "/admin/peer/view/?NetworkID=%d&PeerIP=%d", peer.NetworkID, peer.PeerIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerDelete(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, peer, err := a.formGetPeer(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.render("/network/peer-delete.html", w, struct {
|
||||||
|
Session *api.Session
|
||||||
|
Network *api.Network
|
||||||
|
Peer *api.Peer
|
||||||
|
}{s, n, peer})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminPeerDeleteSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, peer, err := a.formGetPeer(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := a.api.Peer_Delete(n.NetworkID, peer.PeerIP); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return a.redirect(w, r, "/admin/network/view/?NetworkID=%d", n.NetworkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) _adminNetworkHosts(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
n, peers, err := a.formGetNetworkPeers(r.Form)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b := strings.Builder{}
|
||||||
|
|
||||||
|
for _, peer := range peers {
|
||||||
|
ip := n.Network
|
||||||
|
ip[3] = peer.PeerIP
|
||||||
|
b.WriteString(netip.AddrFrom4([4]byte(ip)).String())
|
||||||
|
b.WriteString(" ")
|
||||||
|
b.WriteString(peer.Name)
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(b.String()))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _adminPasswordEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _adminPasswordEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
||||||
@ -143,194 +308,61 @@ func (a *App) _adminPasswordSubmit(s *api.Session, w http.ResponseWriter, r *htt
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.api.Config_UpdatePassword(hash); err != nil {
|
conf.Password = hash
|
||||||
|
|
||||||
|
if err := a.api.Config_Update(conf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.redirect(w, r, "/admin/config/")
|
return a.redirect(w, r, "/admin/config/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) _adminHosts(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
conf := a.api.Config_Get()
|
|
||||||
|
|
||||||
peers, err := a.api.Peer_List()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b := strings.Builder{}
|
|
||||||
|
|
||||||
for _, peer := range peers {
|
|
||||||
ip := conf.VPNNetwork
|
|
||||||
ip[3] = peer.PeerIP
|
|
||||||
b.WriteString(netip.AddrFrom4([4]byte(ip)).String())
|
|
||||||
b.WriteString(" ")
|
|
||||||
b.WriteString(peer.Name)
|
|
||||||
b.WriteString("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Write([]byte(b.String()))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerCreate(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
return a.render("/admin-peer-create.html", w, struct{ Session *api.Session }{s})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerCreateSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
var ipStr string
|
|
||||||
|
|
||||||
p := &api.Peer{}
|
|
||||||
err := webutil.NewFormScanner(r.Form).
|
|
||||||
Scan("IP", &p.PeerIP).
|
|
||||||
Scan("Name", &p.Name).
|
|
||||||
Scan("PublicIP", &ipStr).
|
|
||||||
Scan("Port", &p.Port).
|
|
||||||
Scan("Relay", &p.Relay).
|
|
||||||
Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.PublicIP, err = stringToIP(ipStr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := a.api.Peer_CreateNew(p); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return a.redirect(w, r, "/admin/peer/view/?PeerIP=%d", p.PeerIP)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerView(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
var peerIP byte
|
|
||||||
err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
peer, err := a.api.Peer_Get(peerIP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.render("/admin-peer-view.html", w, struct {
|
|
||||||
Session *api.Session
|
|
||||||
Peer *api.Peer
|
|
||||||
}{s, peer})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
var peerIP byte
|
|
||||||
err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
peer, err := a.api.Peer_Get(peerIP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.render("/admin-peer-edit.html", w, struct {
|
|
||||||
Session *api.Session
|
|
||||||
Peer *api.Peer
|
|
||||||
}{s, peer})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerEditSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
var (
|
|
||||||
peerIP byte
|
|
||||||
ipStr string
|
|
||||||
)
|
|
||||||
|
|
||||||
err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
peer, err := a.api.Peer_Get(peerIP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = webutil.NewFormScanner(r.Form).
|
|
||||||
Scan("Name", &peer.Name).
|
|
||||||
Scan("PublicIP", &ipStr).
|
|
||||||
Scan("Port", &peer.Port).
|
|
||||||
Scan("Relay", &peer.Relay).
|
|
||||||
Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if peer.PublicIP, err = stringToIP(ipStr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = a.api.Peer_Update(peer); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.redirect(w, r, "/admin/peer/view/?PeerIP=%d", peer.PeerIP)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerDelete(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
var peerIP byte
|
|
||||||
err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
peer, err := a.api.Peer_Get(peerIP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.render("/admin-peer-delete.html", w, struct {
|
|
||||||
Session *api.Session
|
|
||||||
Peer *api.Peer
|
|
||||||
}{s, peer})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _adminPeerDeleteSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error {
|
|
||||||
var peerIP byte
|
|
||||||
err := webutil.NewFormScanner(r.Form).Scan("PeerIP", &peerIP).Error()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := a.api.Peer_Delete(peerIP); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.redirect(w, r, "/admin/peer/list/")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request) error {
|
func (a *App) _peerInit(peer *api.Peer, w http.ResponseWriter, r *http.Request) error {
|
||||||
args := m.PeerInitArgs{}
|
args := m.PeerInitArgs{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := a.api.Peer_Init(peer, args)
|
net, err := a.api.Network_Get(peer.NetworkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.sendJSON(w, conf)
|
if err := a.api.Peer_Init(peer, args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := m.PeerInitResp{
|
||||||
|
PeerIP: peer.PeerIP,
|
||||||
|
Network: net.Network,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.NetworkState.Peers, err = a.peersArray(net.NetworkID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.sendJSON(w, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
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.api.Peer_List()
|
|
||||||
|
peers, err := a.peersArray(peer.NetworkID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return a.sendJSON(w, m.NetworkState{Peers: peers})
|
||||||
|
}
|
||||||
|
|
||||||
state := m.NetworkState{}
|
func (a *App) peersArray(networkID int64) (peers [256]*m.Peer, err error) {
|
||||||
|
l, err := a.api.Peer_List(networkID)
|
||||||
|
if err != nil {
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
for _, p := range peers {
|
for _, p := range l {
|
||||||
if len(p.PubKey) != 0 {
|
if len(p.PubKey) != 0 {
|
||||||
state.Peers[p.PeerIP] = &m.Peer{
|
peers[p.PeerIP] = &m.Peer{
|
||||||
PeerIP: p.PeerIP,
|
PeerIP: p.PeerIP,
|
||||||
Version: p.Version,
|
Version: p.Version,
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
@ -343,5 +375,5 @@ func (a *App) _peerFetchState(peer *api.Peer, w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.sendJSON(w, state)
|
return
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,17 @@ func (a *App) registerRoutes() {
|
|||||||
a.handleNotSignedIn("GET /sign-in/", a._signin)
|
a.handleNotSignedIn("GET /sign-in/", a._signin)
|
||||||
a.handleNotSignedIn("POST /sign-in/", a._signinSubmit)
|
a.handleNotSignedIn("POST /sign-in/", a._signinSubmit)
|
||||||
|
|
||||||
a.handleSignedIn("GET /admin/config/", a._adminConfig)
|
|
||||||
a.handleSignedIn("GET /admin/config/edit/", a._adminConfigEdit)
|
|
||||||
a.handleSignedIn("POST /admin/config/edit/", a._adminConfigEditSubmit)
|
|
||||||
a.handleSignedIn("GET /admin/sign-out/", a._adminSignOut)
|
a.handleSignedIn("GET /admin/sign-out/", a._adminSignOut)
|
||||||
a.handleSignedIn("POST /admin/sign-out/", a._adminSignOutSubmit)
|
a.handleSignedIn("POST /admin/sign-out/", a._adminSignOutSubmit)
|
||||||
a.handleSignedIn("GET /admin/password/edit/", a._adminPasswordEdit)
|
|
||||||
a.handleSignedIn("POST /admin/password/edit/", a._adminPasswordSubmit)
|
a.handleSignedIn("GET /admin/network/list/", a._adminNetworkList)
|
||||||
a.handleSignedIn("GET /admin/peer/hosts/", a._adminHosts)
|
a.handleSignedIn("GET /admin/network/create/", a._adminNetworkCreate)
|
||||||
|
a.handleSignedIn("POST /admin/network/create/", a._adminNetworkCreateSubmit)
|
||||||
|
a.handleSignedIn("GET /admin/network/delete/", a._adminNetworkDelete)
|
||||||
|
a.handleSignedIn("POST /admin/network/delete/", a._adminNetworkDeleteSubmit)
|
||||||
|
|
||||||
|
a.handleSignedIn("GET /admin/network/view/", a._adminNetworkView)
|
||||||
|
a.handleSignedIn("GET /admin/network/hosts/", a._adminNetworkHosts)
|
||||||
a.handleSignedIn("GET /admin/peer/create/", a._adminPeerCreate)
|
a.handleSignedIn("GET /admin/peer/create/", a._adminPeerCreate)
|
||||||
a.handleSignedIn("POST /admin/peer/create/", a._adminPeerCreateSubmit)
|
a.handleSignedIn("POST /admin/peer/create/", a._adminPeerCreateSubmit)
|
||||||
a.handleSignedIn("GET /admin/peer/view/", a._adminPeerView)
|
a.handleSignedIn("GET /admin/peer/view/", a._adminPeerView)
|
||||||
@ -25,6 +28,9 @@ func (a *App) registerRoutes() {
|
|||||||
a.handleSignedIn("GET /admin/peer/delete/", a._adminPeerDelete)
|
a.handleSignedIn("GET /admin/peer/delete/", a._adminPeerDelete)
|
||||||
a.handleSignedIn("POST /admin/peer/delete/", a._adminPeerDeleteSubmit)
|
a.handleSignedIn("POST /admin/peer/delete/", a._adminPeerDeleteSubmit)
|
||||||
|
|
||||||
|
a.handleSignedIn("GET /admin/password/edit/", a._adminPasswordEdit)
|
||||||
|
a.handleSignedIn("POST /admin/password/edit/", a._adminPasswordSubmit)
|
||||||
|
|
||||||
a.handlePeer("POST /peer/init/", a._peerInit)
|
a.handlePeer("POST /peer/init/", a._peerInit)
|
||||||
a.handlePeer("GET /peer/fetch-state/", a._peerFetchState)
|
a.handlePeer("GET /peer/fetch-state/", a._peerFetchState)
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
{{define "body" -}}
|
|
||||||
<h2>Config</h2>
|
|
||||||
|
|
||||||
<form method="POST">
|
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
|
||||||
<p>
|
|
||||||
<label>Hub Address</label><br>
|
|
||||||
<input type="url" name="HubAddress" value="{{.Config.HubAddress}}">
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>VPN Network</label><br>
|
|
||||||
<input type="text" name="VPNNetwork" value="{{ipToString .Config.VPNNetwork}}">
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<button type="submit">Save</button>
|
|
||||||
<a href="/admin/config/">Cancel</a>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{{- end}}
|
|
19
hub/templates/admin-network-create.html
Normal file
19
hub/templates/admin-network-create.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{{define "body" -}}
|
||||||
|
<h2>Create Network</h2>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
||||||
|
<p>
|
||||||
|
<label>Name</label><br>
|
||||||
|
<input type="text" name="Name">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label>Network /24</label><br>
|
||||||
|
<input type="text" name="Network">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<button type="submit">Save</button>
|
||||||
|
<a href="/admin/network/list/">Cancel</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
{{- end}}
|
38
hub/templates/admin-network-list.html
Normal file
38
hub/templates/admin-network-list.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{{define "body" -}}
|
||||||
|
<h2>Networks</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="/admin/network/create/">Create</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{{if .Networks -}}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Network</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range .Networks -}}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="/admin/network/view/?NetworkID={{.NetworkID}}">
|
||||||
|
{{.Name}}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>{{ipToString .Network}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
{{- end}}
|
||||||
|
</table>
|
||||||
|
{{- else}}
|
||||||
|
<p>No networks.</p>
|
||||||
|
{{- end}}
|
||||||
|
|
||||||
|
<h3>Settings</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="/admin/password/edit/">Password</a></li>
|
||||||
|
</ul>
|
||||||
|
{{- end}}
|
@ -1,36 +0,0 @@
|
|||||||
{{define "body" -}}
|
|
||||||
<h2>Delete Peer</h2>
|
|
||||||
|
|
||||||
{{with .Peer -}}
|
|
||||||
<form method="POST">
|
|
||||||
<input type="hidden" name="CSRF" value="{{$.Session.CSRF}}">
|
|
||||||
<p>
|
|
||||||
<label>Peer IP</label><br>
|
|
||||||
<input type="number" name="PeerIP" value="{{.PeerIP}}" disabled>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Name</label><br>
|
|
||||||
<input type="text" value="{{.Name}}" disabled>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Public IP</label><br>
|
|
||||||
<input type="text" value="{{ipToString .PublicIP}}" disabled>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Port</label><br>
|
|
||||||
<input type="number" value="{{.Port}}" disabled>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" {{if .Relay}}checked{{end}} disabled>
|
|
||||||
Relay
|
|
||||||
</label>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<button type="submit">Delete</button>
|
|
||||||
<a href="/admin/peer/view/?PeerIP={{.PeerIP}}">Cancel</a>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
{{- end}}
|
|
||||||
|
|
||||||
{{- end}}
|
|
@ -1,13 +0,0 @@
|
|||||||
{{define "body" -}}
|
|
||||||
<h2>Initialize Peer</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Configure the peer with the following URL:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
{{.HubAddress}}/peer/init/?Code={{.Code}}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
<a href="/admin/config/">Done</a>
|
|
||||||
</p>
|
|
||||||
{{- end}}
|
|
@ -1,13 +0,0 @@
|
|||||||
{{define "body" -}}
|
|
||||||
<h2>Create Peer</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Configure the peer with the following URL:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
{{.HubAddress}}/peer/create/?Code={{.Code}}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
<a href="/admin/config/">Done</a>
|
|
||||||
</p>
|
|
||||||
{{- end}}
|
|
@ -5,7 +5,7 @@
|
|||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
||||||
<p>
|
<p>
|
||||||
<button type="submit">Sign Out</button>
|
<button type="submit">Sign Out</button>
|
||||||
<a href="/admin/config/">Cancel</a>
|
<a href="/">Cancel</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<h1>VPPN</h1>
|
<h1>VPPN</h1>
|
||||||
<nav>
|
<nav>
|
||||||
{{if .Session.SignedIn -}}
|
{{if .Session.SignedIn -}}
|
||||||
<a href="/admin/config/">Home</a> /
|
<a href="/admin/networks/list/">Home</a> /
|
||||||
<a href="/admin/sign-out/">Sign out</a>
|
<a href="/admin/sign-out/">Sign out</a>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
</nav>
|
</nav>
|
||||||
|
25
hub/templates/network/base.html
Normal file
25
hub/templates/network/base.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>VPPN Hub</title>
|
||||||
|
<link rel="stylesheet" href="/static/new.min.css">
|
||||||
|
<link rel="stylesheet" href="/static/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>VPPN</h1>
|
||||||
|
<nav>
|
||||||
|
{{if .Session.SignedIn -}}
|
||||||
|
<a href="/admin/networks/list/">Home</a> /
|
||||||
|
<a href="/admin/sign-out/">Sign out</a>
|
||||||
|
{{- end}}
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<h2>
|
||||||
|
Network:
|
||||||
|
<a href="/admin/network/view/?NetworkID={{.Network.NetworkID}}">{{.Network.Name}}</a>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{{block "body" .}}There's nothing here.{{end}}
|
||||||
|
</body>
|
||||||
|
</html>
|
16
hub/templates/network/network-delete.html
Normal file
16
hub/templates/network/network-delete.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{{define "body" -}}
|
||||||
|
<h3>Delete</h3>
|
||||||
|
|
||||||
|
{{if .Peers -}}
|
||||||
|
<p>You must first delete all peers.</p>
|
||||||
|
{{- else -}}
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
||||||
|
<input type="hidden" name="NetworkID" value="{{.Network.NetworkID}}">
|
||||||
|
<p>
|
||||||
|
<button type="submit">Delete</button>
|
||||||
|
<a href="/admin/network/view/?NetworkID={{.Network.NetworkID}}">Cancel</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
{{- end}}
|
||||||
|
{{- end}}
|
@ -1,27 +1,20 @@
|
|||||||
{{define "body" -}}
|
{{define "body" -}}
|
||||||
<h2>Config</h2>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="/admin/config/edit/">Edit</a> /
|
<a href="/admin/network/delete/?NetworkID={{.Network.NetworkID}}">Delete</a> /
|
||||||
<a href="/admin/password/edit/">Change Password</a>
|
<a href="/admin/network/hosts/?NetworkID={{.Network.NetworkID}}">Hosts</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table class="def-list">
|
<table class="def-list">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Hub Address</td>
|
<td>Network</td>
|
||||||
<td>{{.Config.HubAddress}}</td>
|
<td>{{ipToString .Network.Network}}/24</td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>VPN Network</td>
|
|
||||||
<td>{{ipToString .Config.VPNNetwork}}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2>Peers</h2>
|
<h3>Peers</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="/admin/peer/create/">Add Peer</a> /
|
<a href="/admin/peer/create/?NetworkID={{.Network.NetworkID}}">Create</a>
|
||||||
<a href="/admin/peer/hosts/">Hosts</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{{if .Peers -}}
|
{{if .Peers -}}
|
||||||
@ -39,7 +32,7 @@
|
|||||||
{{range .Peers -}}
|
{{range .Peers -}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="/admin/peer/view/?PeerIP={{.PeerIP}}">
|
<a href="/admin/peer/view/?NetworkID={{$.Network.NetworkID}}&PeerIP={{.PeerIP}}">
|
||||||
{{.PeerIP}}
|
{{.PeerIP}}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
@ -1,8 +1,9 @@
|
|||||||
{{define "body" -}}
|
{{define "body" -}}
|
||||||
<h2>New Peer</h2>
|
<h3>New Peer</h3>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
<input type="hidden" name="CSRF" value="{{.Session.CSRF}}">
|
||||||
|
<input type="hidden" name="NetworkID" value="{{.Network.NetworkID}}">
|
||||||
<p>
|
<p>
|
||||||
<label>IP</label><br>
|
<label>IP</label><br>
|
||||||
<input type="number" name="IP" min="1" max="255" value="0">
|
<input type="number" name="IP" min="1" max="255" value="0">
|
||||||
@ -27,7 +28,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<button type="submit">Save</button>
|
<button type="submit">Save</button>
|
||||||
<a href="/admin/config/">Cancel</a>
|
<a href="/admin/network/view/?NetworkID={{.Network.NetworkID}}">Cancel</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
15
hub/templates/network/peer-delete.html
Normal file
15
hub/templates/network/peer-delete.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{{define "body" -}}
|
||||||
|
<h3>Delete {{.Peer.Name}}</h3>
|
||||||
|
|
||||||
|
{{with .Peer -}}
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="CSRF" value="{{$.Session.CSRF}}">
|
||||||
|
<input type="hidden" name="NetworkID" value="{{.NetworkID}}">
|
||||||
|
<input type="hidden" name="NetworkID" value="{{.PeerIP}}">
|
||||||
|
<p>
|
||||||
|
<button type="submit">Delete</button>
|
||||||
|
<a href="/admin/peer/view/?PeerIP={{.PeerIP}}&NetworkID={{.NetworkID}}">Cancel</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
{{- end}}
|
||||||
|
{{- end}}
|
@ -6,7 +6,7 @@
|
|||||||
<input type="hidden" name="CSRF" value="{{$.Session.CSRF}}">
|
<input type="hidden" name="CSRF" value="{{$.Session.CSRF}}">
|
||||||
<p>
|
<p>
|
||||||
<label>Peer IP</label><br>
|
<label>Peer IP</label><br>
|
||||||
<input type="number" name="PeerIP" value="{{.PeerIP}}" disabled>
|
<input type="text" value="{{.PeerIP}}" disabled>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label>Name</label><br>
|
<label>Name</label><br>
|
||||||
@ -28,9 +28,8 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<button type="submit">Save</button>
|
<button type="submit">Save</button>
|
||||||
<a href="/admin/peer/view/?PeerIP={{.PeerIP}}">Cancel</a>
|
<a href="/admin/peer/view/?NetworkID={{$.Network.NetworkID}}&PeerIP={{.PeerIP}}">Cancel</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
{{- end}}
|
{{- end}}
|
@ -1,20 +1,25 @@
|
|||||||
{{define "body" -}}
|
{{define "body" -}}
|
||||||
<h2>Peer</h2>
|
<h3>{{.Peer.Name}}</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="/admin/peer/edit/?PeerIP={{.Peer.PeerIP}}">Edit</a> /
|
<a href="/admin/peer/edit/?NetworkID={{.Network.NetworkID}}&PeerIP={{.Peer.PeerIP}}">Edit</a> /
|
||||||
<a href="/admin/peer/delete/?PeerIP={{.Peer.PeerIP}}">Delete</a>
|
<a href="/admin/peer/delete/?NetworkID={{.Network.NetworkID}}&PeerIP={{.Peer.PeerIP}}">Delete</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{{with .Peer -}}
|
{{with .Peer -}}
|
||||||
<table class="def-list">
|
<table class="def-list">
|
||||||
<tr><td>Peer IP</td><td>{{.PeerIP}}</td></tr>
|
<tr><td>Peer IP</td><td>{{.PeerIP}}</td></tr>
|
||||||
<tr><td>Name</td><td>{{.Name}}</td></tr>
|
|
||||||
<tr><td>Public IP</td><td>{{ipToString .PublicIP}}</td></tr>
|
<tr><td>Public IP</td><td>{{ipToString .PublicIP}}</td></tr>
|
||||||
<tr><td>Port</td><td>{{.Port}}</td></tr>
|
<tr><td>Port</td><td>{{.Port}}</td></tr>
|
||||||
<tr><td>Relay</td><td>{{if .Relay}}T{{else}}F{{end}}</td></tr>
|
<tr><td>Relay</td><td>{{if .Relay}}T{{else}}F{{end}}</td></tr>
|
||||||
<tr><td>API Key</td><td>{{.APIKey}}</td></tr>
|
</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>API Key</summary>
|
||||||
|
<p>{{.APIKey}}</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
{{- end}}
|
{{- end}}
|
@ -6,12 +6,10 @@ type PeerInitArgs struct {
|
|||||||
PubSignKey []byte
|
PubSignKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeerConfig struct {
|
type PeerInitResp struct {
|
||||||
PeerIP byte
|
PeerIP byte
|
||||||
Network []byte
|
Network []byte
|
||||||
PublicIP []byte
|
NetworkState NetworkState
|
||||||
Port uint16
|
|
||||||
Relay bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
|
@ -9,7 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type localConfig struct {
|
type localConfig struct {
|
||||||
m.PeerConfig
|
PeerIP byte
|
||||||
|
Network []byte
|
||||||
PubKey []byte
|
PubKey []byte
|
||||||
PrivKey []byte
|
PrivKey []byte
|
||||||
PubSignKey []byte
|
PubSignKey []byte
|
||||||
@ -25,11 +26,11 @@ func configDir(netName string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func peerConfigPath(netName string) string {
|
func peerConfigPath(netName string) string {
|
||||||
return filepath.Join(configDir(netName), "peer-config.json")
|
return filepath.Join(configDir(netName), "config.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
func peerStatePath(netName string) string {
|
func peerStatePath(netName string) string {
|
||||||
return filepath.Join(configDir(netName), "peer-state.json")
|
return filepath.Join(configDir(netName), "state.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeJson(x any, outPath string) error {
|
func storeJson(x any, outPath string) error {
|
||||||
|
@ -16,12 +16,12 @@ func TestFilePaths(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
path := peerConfigPath("netName")
|
path := peerConfigPath("netName")
|
||||||
if path != filepath.Join(confDir, "peer-config.json") {
|
if path != filepath.Join(confDir, "config.json") {
|
||||||
t.Fatal(path)
|
t.Fatal(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = peerStatePath("netName")
|
path = peerStatePath("netName")
|
||||||
if path != filepath.Join(confDir, "peer-state.json") {
|
if path != filepath.Join(confDir, "state.json") {
|
||||||
t.Fatal(path)
|
t.Fatal(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Main() {
|
func Main() {
|
||||||
conf := peerConfig{}
|
conf := mainArgs{}
|
||||||
|
|
||||||
flag.StringVar(&conf.NetName, "name", "", "[REQUIRED] The network name.")
|
flag.StringVar(&conf.NetName, "name", "", "[REQUIRED] The network name.")
|
||||||
flag.StringVar(&conf.HubAddress, "hub-address", "", "[REQUIRED] The hub address.")
|
flag.StringVar(&conf.HubAddress, "hub-address", "", "[REQUIRED] The hub address.")
|
||||||
|
@ -65,6 +65,7 @@ func runMCReaderInner(
|
|||||||
SrcIP: h.SourceIP,
|
SrcIP: h.SourceIP,
|
||||||
SrcAddr: remoteAddr,
|
SrcAddr: remoteAddr,
|
||||||
}
|
}
|
||||||
|
logf("Got discovery packet from peer %d.", h.SourceIP)
|
||||||
handleControlMsg(h.SourceIP, msg)
|
handleControlMsg(h.SourceIP, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ func runMCWriter(localIP byte, signingKey []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for range time.Tick(broadcastInterval) {
|
for range time.Tick(broadcastInterval) {
|
||||||
|
log.Printf("[MCWriter] Broadcasting on %v...", multicastAddr)
|
||||||
_, err := conn.WriteToUDP(discoveryPacket, multicastAddr)
|
_, err := conn.WriteToUDP(discoveryPacket, multicastAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[MCWriter] Failed to write multicast: %v", err)
|
log.Printf("[MCWriter] Failed to write multicast: %v", err)
|
||||||
|
60
peer/peer.go
60
peer/peer.go
@ -25,35 +25,42 @@ type peerMain struct {
|
|||||||
super *supervisor
|
super *supervisor
|
||||||
}
|
}
|
||||||
|
|
||||||
type peerConfig struct {
|
type mainArgs struct {
|
||||||
NetName string
|
NetName string
|
||||||
HubAddress string
|
HubAddress string
|
||||||
APIKey string
|
APIKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPeerMain(conf peerConfig) *peerMain {
|
func newPeerMain(args mainArgs) *peerMain {
|
||||||
logf := func(s string, args ...any) {
|
logf := func(s string, args ...any) {
|
||||||
log.Printf("[Main] "+s, args...)
|
log.Printf("[Main] "+s, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := loadPeerConfig(conf.NetName)
|
config, err := loadPeerConfig(args.NetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("Failed to load configuration: %v", err)
|
logf("Failed to load configuration: %v", err)
|
||||||
logf("Initializing...")
|
logf("Initializing...")
|
||||||
initPeerWithHub(conf)
|
initPeerWithHub(args)
|
||||||
|
|
||||||
config, err = loadPeerConfig(conf.NetName)
|
config, err = loadPeerConfig(args.NetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to load configuration: %v", err)
|
log.Fatalf("Failed to load configuration: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, err := openInterface(config.Network, config.PeerIP, conf.NetName)
|
state, err := loadNetworkState(args.NetName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to load network state: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
iface, err := openInterface(config.Network, config.PeerIP, args.NetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to open interface: %v", err)
|
log.Fatalf("Failed to open interface: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", config.Port))
|
localPeer := state.Peers[config.PeerIP]
|
||||||
|
|
||||||
|
myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", localPeer.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to resolve UDP address: %v", err)
|
log.Fatalf("Failed to resolve UDP address: %v", err)
|
||||||
}
|
}
|
||||||
@ -80,19 +87,19 @@ func newPeerMain(conf peerConfig) *peerMain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var localAddr netip.AddrPort
|
var localAddr netip.AddrPort
|
||||||
ip, localAddrValid := netip.AddrFromSlice(config.PublicIP)
|
ip, localAddrValid := netip.AddrFromSlice(localPeer.PublicIP)
|
||||||
if localAddrValid {
|
if localAddrValid {
|
||||||
localAddr = netip.AddrPortFrom(ip, config.Port)
|
localAddr = netip.AddrPortFrom(ip, localPeer.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
rt := newRoutingTable(config.PeerIP, localAddr)
|
rt := newRoutingTable(localPeer.PeerIP, localAddr)
|
||||||
rtPtr := &atomic.Pointer[routingTable]{}
|
rtPtr := &atomic.Pointer[routingTable]{}
|
||||||
rtPtr.Store(&rt)
|
rtPtr.Store(&rt)
|
||||||
|
|
||||||
ifReader := newIFReader(iface, writeToUDPAddrPort, rtPtr)
|
ifReader := newIFReader(iface, writeToUDPAddrPort, rtPtr)
|
||||||
super := newSupervisor(writeToUDPAddrPort, rtPtr, config.PrivKey)
|
super := newSupervisor(writeToUDPAddrPort, rtPtr, config.PrivKey)
|
||||||
connReader := newConnReader(conn.ReadFromUDPAddrPort, writeToUDPAddrPort, iface, super.HandleControlMsg, rtPtr)
|
connReader := newConnReader(conn.ReadFromUDPAddrPort, writeToUDPAddrPort, iface, super.HandleControlMsg, rtPtr)
|
||||||
hubPoller, err := newHubPoller(config.PeerIP, conf.NetName, conf.HubAddress, conf.APIKey, super.HandleControlMsg)
|
hubPoller, err := newHubPoller(config.PeerIP, args.NetName, args.HubAddress, args.APIKey, super.HandleControlMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to create hub poller: %v", err)
|
log.Fatalf("Failed to create hub poller: %v", err)
|
||||||
}
|
}
|
||||||
@ -123,22 +130,22 @@ func (p *peerMain) Run() {
|
|||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initPeerWithHub(conf peerConfig) {
|
func initPeerWithHub(args mainArgs) {
|
||||||
keys := generateKeys()
|
keys := generateKeys()
|
||||||
|
|
||||||
initURL, err := url.Parse(conf.HubAddress)
|
initURL, err := url.Parse(args.HubAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to parse hub URL: %v", err)
|
log.Fatalf("Failed to parse hub URL: %v", err)
|
||||||
}
|
}
|
||||||
initURL.Path = "/peer/init/"
|
initURL.Path = "/peer/init/"
|
||||||
|
|
||||||
args := m.PeerInitArgs{
|
initArgs := m.PeerInitArgs{
|
||||||
EncPubKey: keys.PubKey,
|
EncPubKey: keys.PubKey,
|
||||||
PubSignKey: keys.PubSignKey,
|
PubSignKey: keys.PubSignKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
if err := json.NewEncoder(buf).Encode(args); err != nil {
|
if err := json.NewEncoder(buf).Encode(initArgs); err != nil {
|
||||||
log.Fatalf("Failed to encode init args: %v", err)
|
log.Fatalf("Failed to encode init args: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +153,7 @@ func initPeerWithHub(conf peerConfig) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to construct request: %v", err)
|
log.Fatalf("Failed to construct request: %v", err)
|
||||||
}
|
}
|
||||||
req.SetBasicAuth("", conf.APIKey)
|
req.SetBasicAuth("", args.APIKey)
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -159,17 +166,24 @@ func initPeerWithHub(conf peerConfig) {
|
|||||||
log.Fatalf("Failed to read response body: %v", err)
|
log.Fatalf("Failed to read response body: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
peerConfig := localConfig{}
|
initResp := m.PeerInitResp{}
|
||||||
if err := json.Unmarshal(data, &peerConfig.PeerConfig); err != nil {
|
if err := json.Unmarshal(data, &initResp); err != nil {
|
||||||
log.Fatalf("Failed to parse configuration: %v\n%s", err, data)
|
log.Fatalf("Failed to parse configuration: %v\n%s", err, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
peerConfig.PubKey = keys.PubKey
|
config := localConfig{}
|
||||||
peerConfig.PrivKey = keys.PrivKey
|
config.PeerIP = initResp.PeerIP
|
||||||
peerConfig.PubSignKey = keys.PubSignKey
|
config.Network = initResp.Network
|
||||||
peerConfig.PrivSignKey = keys.PrivSignKey
|
config.PubKey = keys.PubKey
|
||||||
|
config.PrivKey = keys.PrivKey
|
||||||
|
config.PubSignKey = keys.PubSignKey
|
||||||
|
config.PrivSignKey = keys.PrivSignKey
|
||||||
|
|
||||||
if err := storePeerConfig(conf.NetName, peerConfig); err != nil {
|
if err := storeNetworkState(args.NetName, initResp.NetworkState); err != nil {
|
||||||
|
log.Fatalf("Failed to store network state: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := storePeerConfig(args.NetName, config); err != nil {
|
||||||
log.Fatalf("Failed to store configuration: %v", err)
|
log.Fatalf("Failed to store configuration: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user