mirror of
https://github.com/Threnklyn/wg-ui.git
synced 2026-05-19 13:23:30 +02:00
Add basic config
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/mdlayher/wireguardctrl/wgtypes"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
configPath string `json:"-"`
|
||||
PrivateKey string
|
||||
PublicKey string
|
||||
Users map[string]*UserConfig
|
||||
}
|
||||
|
||||
type UserConfig struct {
|
||||
Name string
|
||||
Devices map[string]*DeviceConfig
|
||||
}
|
||||
|
||||
type DeviceConfig struct {
|
||||
Name string
|
||||
PrivateKey string
|
||||
PublicKey string
|
||||
}
|
||||
|
||||
func NewServerConfig(cfgPath string) *ServerConfig {
|
||||
key, err := wgtypes.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := &ServerConfig{
|
||||
configPath: cfgPath,
|
||||
PrivateKey: key.String(),
|
||||
PublicKey: key.PublicKey().String(),
|
||||
Users: make(map[string]*UserConfig),
|
||||
}
|
||||
|
||||
f, err := os.Open(cfgPath)
|
||||
if err == nil {
|
||||
if err = json.NewDecoder(f).Decode(cfg); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Debug("Read server config from file: ", cfgPath)
|
||||
} else if os.IsNotExist(err) {
|
||||
log.Debug("No config found. Creating new: ", cfgPath)
|
||||
err = cfg.Write()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (cfg *ServerConfig) Write() error {
|
||||
data, err := json.MarshalIndent(cfg, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(cfg.configPath, data, 0600)
|
||||
}
|
||||
|
||||
func (cfg *ServerConfig) GetUserConfig(user string) *UserConfig {
|
||||
c, ok := cfg.Users[user]
|
||||
if !ok {
|
||||
log.WithField("user", user).Info("No such user. Creating one.")
|
||||
c = &UserConfig{
|
||||
Name: user,
|
||||
Devices: make(map[string]*DeviceConfig),
|
||||
}
|
||||
cfg.Users[user] = c
|
||||
}
|
||||
return c
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
@@ -20,6 +21,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
dataDir = kingpin.Flag("data-dir", "Directory used for storage").Default("/var/lib/wireguard-ui").String()
|
||||
|
||||
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
|
||||
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
|
||||
|
||||
@@ -30,8 +33,8 @@ var (
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
storage *Storage
|
||||
config *ServerConfig
|
||||
serverConfigPath string
|
||||
Config *ServerConfig
|
||||
}
|
||||
|
||||
type WgLink struct {
|
||||
@@ -56,14 +59,23 @@ func ifname(n string) []byte {
|
||||
}
|
||||
|
||||
func NewServer() *Server {
|
||||
storage := NewStorage()
|
||||
|
||||
server := &Server{
|
||||
storage: storage,
|
||||
config: storage.GetServerConfig(),
|
||||
err := os.MkdirAll(*dataDir, 0700)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("Error initializing data directory: %s", *dataDir)
|
||||
}
|
||||
|
||||
return server
|
||||
cfgPath := path.Join(*dataDir, "config.json")
|
||||
config := NewServerConfig(cfgPath)
|
||||
|
||||
log.Debug("Configuration loaded with public key: ", config.PublicKey)
|
||||
|
||||
s := Server{
|
||||
serverConfigPath: cfgPath,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
log.Debug("Server initialized: ", *dataDir)
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *Server) initInterface() error {
|
||||
@@ -148,7 +160,7 @@ func (s *Server) initInterface() error {
|
||||
}
|
||||
|
||||
log.Debug("Adding wireguard private key")
|
||||
key, err := wgtypes.ParseKey(s.config.PrivateKey)
|
||||
key, err := wgtypes.ParseKey(s.Config.PrivateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -171,6 +183,7 @@ func (s *Server) Start() error {
|
||||
router := httprouter.New()
|
||||
router.GET("/", s.Index)
|
||||
router.GET("/api/v1/users/:user/devices", s.withAuth(s.GetDevices))
|
||||
router.POST("/api/v1/users/:user/devices", s.withAuth(s.CreateDevice))
|
||||
|
||||
log.WithField("listenAddr", *listenAddr).Info("Starting server")
|
||||
return http.ListenAndServe(*listenAddr, router)
|
||||
@@ -218,6 +231,13 @@ func (s *Server) withAuth(handler httprouter.Handle) httprouter.Handle {
|
||||
user := userFromJwtToken(r)
|
||||
if user == "" {
|
||||
user = "anonymous"
|
||||
log.Info("Unauthenticated user: ", user)
|
||||
}
|
||||
|
||||
if user != ps.ByName("user") {
|
||||
log.WithField("user", user).WithField("path", r.URL.Path).Warn("Unauthorized access")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), "user", user)
|
||||
@@ -232,12 +252,29 @@ func (s *Server) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Para
|
||||
|
||||
func (s *Server) GetDevices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
user := r.Context().Value("user")
|
||||
if user != ps.ByName("user") {
|
||||
log.WithField("user", user).WithField("path", r.URL.Path).Warn("Unauthorized access")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
err := json.NewEncoder(w).Encode(s.config)
|
||||
log.Debug(user)
|
||||
err := json.NewEncoder(w).Encode(s.Config)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) CreateDevice(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
user := r.Context().Value("user").(string)
|
||||
log.WithField("user", user).Debug("CreateDevice")
|
||||
|
||||
c := s.Config.GetUserConfig(user)
|
||||
log.Debugf("user config: %#v", c)
|
||||
|
||||
err := s.Config.Write()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(c)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/mdlayher/wireguardctrl/wgtypes"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
dataDir = kingpin.Flag("data-dir", "Directory used for storage").Default("/var/lib/wireguard-ui").String()
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
PrivateKey string
|
||||
PublicKey string
|
||||
Users []*UserConfig
|
||||
}
|
||||
|
||||
type UserConfig struct {
|
||||
Name string
|
||||
Devices []*DeviceConfig
|
||||
}
|
||||
|
||||
type DeviceConfig struct {
|
||||
Name string
|
||||
PrivateKey string
|
||||
PublicKey string
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
serverConfigPath string
|
||||
}
|
||||
|
||||
func NewStorage() *Storage {
|
||||
err := os.MkdirAll(*dataDir, 0700)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("Error initializing data directory: %s", *dataDir)
|
||||
}
|
||||
|
||||
s := Storage{
|
||||
serverConfigPath: path.Join(*dataDir, "config.json"),
|
||||
}
|
||||
log.Debug("Storage initialized: ", *dataDir)
|
||||
return &s
|
||||
}
|
||||
|
||||
func NewServerConfig() *ServerConfig {
|
||||
key, err := wgtypes.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := ServerConfig{
|
||||
PrivateKey: key.String(),
|
||||
PublicKey: key.PublicKey().String(),
|
||||
}
|
||||
|
||||
return &cfg
|
||||
}
|
||||
|
||||
func (cfg *ServerConfig) WriteServerConfig(path string) error {
|
||||
data, err := json.MarshalIndent(cfg, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(path, data, 0600)
|
||||
}
|
||||
|
||||
func (s *Storage) GetServerConfig() *ServerConfig {
|
||||
config := NewServerConfig()
|
||||
|
||||
f, err := os.Open(s.serverConfigPath)
|
||||
if err == nil {
|
||||
if err = json.NewDecoder(f).Decode(config); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Debug("Read server config from file: ", s.serverConfigPath)
|
||||
} else if os.IsNotExist(err) {
|
||||
log.Debug("No config found. Creating new: ", s.serverConfigPath)
|
||||
err = config.WriteServerConfig(s.serverConfigPath)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Debug("Configuration loaded with public key: ", config.PublicKey)
|
||||
return config
|
||||
}
|
||||
Reference in New Issue
Block a user