mirror of
https://github.com/vx3r/wg-gen-web.git
synced 2024-11-04 17:31:17 +00:00
169 lines
4.3 KiB
Go
169 lines
4.3 KiB
Go
|
package core
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"time"
|
||
|
|
||
|
"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/model"
|
||
|
)
|
||
|
|
||
|
// apiError implements a top-level JSON-RPC error.
|
||
|
type apiError struct {
|
||
|
Code int `json:"code"`
|
||
|
Message string `json:"message"`
|
||
|
|
||
|
Data interface{} `json:"data,omitempty"`
|
||
|
}
|
||
|
|
||
|
type apiRequest struct {
|
||
|
Version string `json:"jsonrpc"`
|
||
|
Method string `json:"method"`
|
||
|
Params json.RawMessage `json:"params,omitempty"`
|
||
|
}
|
||
|
|
||
|
type apiResponse struct {
|
||
|
Version string `json:"jsonrpc"`
|
||
|
Result interface{} `json:"result,omitempty"`
|
||
|
Error *apiError `json:"error,omitempty"`
|
||
|
ID json.RawMessage `json:"id"`
|
||
|
}
|
||
|
|
||
|
func fetchWireGuardAPI(reqData apiRequest) (*apiResponse, error) {
|
||
|
apiUrl := os.Getenv("WG_STATS_API")
|
||
|
apiClient := http.Client{
|
||
|
Timeout: time.Second * 2, // Timeout after 2 seconds
|
||
|
}
|
||
|
jsonData, _ := json.Marshal(reqData)
|
||
|
req, err := http.NewRequest(http.MethodPost, apiUrl, bytes.NewBuffer(jsonData))
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
req.Header.Set("User-Agent", "wg-gen-web")
|
||
|
req.Header.Set("Accept", "application/json")
|
||
|
req.Header.Set("Content-Type", "application/json")
|
||
|
req.Header.Set("Cache-Control", "no-cache")
|
||
|
|
||
|
if os.Getenv("WG_STATS_API_USER") != "" {
|
||
|
req.SetBasicAuth(os.Getenv("WG_STATS_API_USER"), os.Getenv("WG_STATS_API_PASS"))
|
||
|
}
|
||
|
|
||
|
res, getErr := apiClient.Do(req)
|
||
|
if getErr != nil {
|
||
|
return nil, getErr
|
||
|
}
|
||
|
|
||
|
if res.Body != nil {
|
||
|
defer res.Body.Close()
|
||
|
}
|
||
|
|
||
|
body, readErr := ioutil.ReadAll(res.Body)
|
||
|
if readErr != nil {
|
||
|
return nil, readErr
|
||
|
}
|
||
|
|
||
|
response := apiResponse{}
|
||
|
jsonErr := json.Unmarshal(body, &response)
|
||
|
if jsonErr != nil {
|
||
|
return nil, jsonErr
|
||
|
}
|
||
|
|
||
|
return &response, nil
|
||
|
}
|
||
|
|
||
|
// ReadInterfaceStatus object, create default one
|
||
|
func ReadInterfaceStatus() (*model.InterfaceStatus, error) {
|
||
|
interfaceStatus := &model.InterfaceStatus{
|
||
|
Name: "unknown",
|
||
|
DeviceType: "unknown",
|
||
|
ListenPort: 0,
|
||
|
NumberOfPeers: 0,
|
||
|
PublicKey: "",
|
||
|
}
|
||
|
|
||
|
data, err := fetchWireGuardAPI(apiRequest{
|
||
|
Version: "2.0",
|
||
|
Method: "GetDeviceInfo",
|
||
|
Params: nil,
|
||
|
})
|
||
|
if err != nil {
|
||
|
return interfaceStatus, err
|
||
|
}
|
||
|
|
||
|
resultData := data.Result.(map[string]interface{})
|
||
|
device := resultData["device"].(map[string]interface{})
|
||
|
interfaceStatus.Name = device["name"].(string)
|
||
|
interfaceStatus.DeviceType = device["type"].(string)
|
||
|
interfaceStatus.PublicKey = device["public_key"].(string)
|
||
|
interfaceStatus.ListenPort = int(device["listen_port"].(float64))
|
||
|
interfaceStatus.NumberOfPeers = int(device["num_peers"].(float64))
|
||
|
|
||
|
return interfaceStatus, nil
|
||
|
}
|
||
|
|
||
|
// ReadClientStatus object, create default one, last recent active client is listed first
|
||
|
func ReadClientStatus() ([]*model.ClientStatus, error) {
|
||
|
var clientStatus []*model.ClientStatus
|
||
|
|
||
|
data, err := fetchWireGuardAPI(apiRequest{
|
||
|
Version: "2.0",
|
||
|
Method: "ListPeers",
|
||
|
Params: []byte("{}"),
|
||
|
})
|
||
|
if err != nil {
|
||
|
return clientStatus, err
|
||
|
}
|
||
|
|
||
|
resultData := data.Result.(map[string]interface{})
|
||
|
peers := resultData["peers"].([]interface{})
|
||
|
|
||
|
clients, err := ReadClients()
|
||
|
withClientDetails := true
|
||
|
if err != nil {
|
||
|
withClientDetails = false
|
||
|
}
|
||
|
|
||
|
for _, tmpPeer := range peers {
|
||
|
peer := tmpPeer.(map[string]interface{})
|
||
|
peerHandshake, _ := time.Parse(time.RFC3339Nano, peer["last_handshake"].(string))
|
||
|
peerIPs := peer["allowed_ips"].([]interface{})
|
||
|
peerAddresses := make([]string, len(peerIPs))
|
||
|
for i, peerIP := range peerIPs {
|
||
|
peerAddresses[i] = peerIP.(string)
|
||
|
}
|
||
|
|
||
|
newClientStatus := &model.ClientStatus{
|
||
|
PublicKey: peer["public_key"].(string),
|
||
|
HasPresharedKey: peer["has_preshared_key"].(bool),
|
||
|
ProtocolVersion: int(peer["protocol_version"].(float64)),
|
||
|
Name: "UNKNOWN",
|
||
|
Email: "UNKNOWN",
|
||
|
Connected: false,
|
||
|
AllowedIPs: peerAddresses,
|
||
|
Endpoint: peer["endpoint"].(string),
|
||
|
LastHandshake: peerHandshake,
|
||
|
ReceivedBytes: int(peer["receive_bytes"].(float64)),
|
||
|
TransmittedBytes: int(peer["transmit_bytes"].(float64)),
|
||
|
}
|
||
|
|
||
|
if withClientDetails {
|
||
|
for _, client := range clients {
|
||
|
if client.PublicKey != newClientStatus.PublicKey {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
newClientStatus.Name = client.Name
|
||
|
newClientStatus.Email = client.Email
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
clientStatus = append(clientStatus, newClientStatus)
|
||
|
}
|
||
|
return clientStatus, nil
|
||
|
}
|