138 lines
4.0 KiB
Go
138 lines
4.0 KiB
Go
|
package hvpnnode3
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"log/slog"
|
||
|
"net"
|
||
|
"net/http"
|
||
|
|
||
|
"github.com/felixge/httpsnoop"
|
||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||
|
|
||
|
"gitea.hbanafa.com/HeshamTB/hvpn-node3/proto"
|
||
|
)
|
||
|
|
||
|
|
||
|
func HandleGetPeer(wgLink *WGLink) http.HandlerFunc {
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
w.WriteHeader(http.StatusNotImplemented)
|
||
|
slog.Info("GET Peer is not implemented")
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func HandleGetPeers(wgLink *WGLink) http.HandlerFunc {
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
dev, err := wgLink.Device(wgLink.Name)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
slog.Error(err.Error())
|
||
|
return
|
||
|
}
|
||
|
var peers []proto.Peer
|
||
|
for _, peer := range dev.Peers {
|
||
|
p := proto.Peer{
|
||
|
Address: peer.AllowedIPs[0].IP,
|
||
|
PublicKey: peer.PublicKey.String(),
|
||
|
PersistentKeepalive: peer.PersistentKeepaliveInterval,
|
||
|
TX: peer.TransmitBytes,
|
||
|
RX: peer.ReceiveBytes,
|
||
|
}
|
||
|
peers = append(peers, p)
|
||
|
}
|
||
|
err = json.NewEncoder(w).Encode(peers)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
func HandlePostPeer(IPPool IPPool, wgLink *WGLink) http.HandlerFunc {
|
||
|
return func(w http.ResponseWriter, r* http.Request) {
|
||
|
peerRequest := proto.CreatePeerRequest{}
|
||
|
err := json.NewDecoder(r.Body).Decode(&peerRequest)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
json.NewEncoder(w).Encode(
|
||
|
&proto.ErrJSONResponse{Message: "Invalid request JSON"},
|
||
|
)
|
||
|
return
|
||
|
}
|
||
|
// TODO: Check if pubkey is already registered
|
||
|
dev, err := wgLink.Device(wgLink.Name)
|
||
|
if err != nil {
|
||
|
slog.Error(err.Error())
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for _, peer := range dev.Peers {
|
||
|
if peer.PublicKey.String() == peerRequest.PublicKey {
|
||
|
w.WriteHeader(http.StatusAccepted)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
newIP, err := IPPool.Allocate()
|
||
|
if err != nil {
|
||
|
slog.Error(err.Error())
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// TODO: Add peer to wg device
|
||
|
// TODO: Declare subnet mask for the service
|
||
|
pkey, _ := wgtypes.GeneratePrivateKey()
|
||
|
newPeer := wgtypes.PeerConfig{
|
||
|
PublicKey: pkey.PublicKey(),
|
||
|
ReplaceAllowedIPs: true,
|
||
|
AllowedIPs: []net.IPNet{
|
||
|
{
|
||
|
IP: newIP,
|
||
|
Mask: net.IPv4Mask(255, 255, 255, 255),
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
err = wgLink.ConfigureDevice(
|
||
|
wgLink.Name,
|
||
|
wgtypes.Config{
|
||
|
Peers: []wgtypes.PeerConfig{
|
||
|
newPeer,
|
||
|
},
|
||
|
ReplacePeers: false,
|
||
|
},
|
||
|
)
|
||
|
if err != nil {
|
||
|
slog.Error(err.Error())
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
json.NewEncoder(w).Encode(
|
||
|
&proto.Peer{
|
||
|
Address: newIP,
|
||
|
MTU: 1384,
|
||
|
PublicKey: peerRequest.PublicKey,
|
||
|
Endpoint: "vpn.test.com:8487",
|
||
|
AllowedIPs: net.ParseIP("0.0.0.0/0"),
|
||
|
PersistentKeepalive: 25,
|
||
|
},
|
||
|
)
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
func HttpLogHandler2(h http.Handler) http.Handler {
|
||
|
// https://blog.kowalczyk.info/article/e00e89c3841e4f8c8c769a78b8a90b47/logging-http-requests-in-go.html
|
||
|
fn := func(w http.ResponseWriter, r* http.Request) {
|
||
|
m := httpsnoop.CaptureMetrics(h, w, r)
|
||
|
msg := fmt.Sprintf(
|
||
|
"%s %s %s %d %s", r.RemoteAddr, r.Method,
|
||
|
r.URL.String(),m.Code, m.Duration)
|
||
|
slog.Info(msg)
|
||
|
}
|
||
|
return http.HandlerFunc(fn)
|
||
|
}
|