mirror of
https://github.com/Threnklyn/wg-ui.git
synced 2026-06-04 20:59:16 +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"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
@@ -20,6 +21,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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()
|
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
|
||||||
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
|
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
|
||||||
|
|
||||||
@@ -30,8 +33,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
storage *Storage
|
serverConfigPath string
|
||||||
config *ServerConfig
|
Config *ServerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type WgLink struct {
|
type WgLink struct {
|
||||||
@@ -56,14 +59,23 @@ func ifname(n string) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewServer() *Server {
|
func NewServer() *Server {
|
||||||
storage := NewStorage()
|
err := os.MkdirAll(*dataDir, 0700)
|
||||||
|
if err != nil {
|
||||||
server := &Server{
|
log.WithError(err).Fatalf("Error initializing data directory: %s", *dataDir)
|
||||||
storage: storage,
|
|
||||||
config: storage.GetServerConfig(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
func (s *Server) initInterface() error {
|
||||||
@@ -148,7 +160,7 @@ func (s *Server) initInterface() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("Adding wireguard private key")
|
log.Debug("Adding wireguard private key")
|
||||||
key, err := wgtypes.ParseKey(s.config.PrivateKey)
|
key, err := wgtypes.ParseKey(s.Config.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -171,6 +183,7 @@ func (s *Server) Start() error {
|
|||||||
router := httprouter.New()
|
router := httprouter.New()
|
||||||
router.GET("/", s.Index)
|
router.GET("/", s.Index)
|
||||||
router.GET("/api/v1/users/:user/devices", s.withAuth(s.GetDevices))
|
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")
|
log.WithField("listenAddr", *listenAddr).Info("Starting server")
|
||||||
return http.ListenAndServe(*listenAddr, router)
|
return http.ListenAndServe(*listenAddr, router)
|
||||||
@@ -218,6 +231,13 @@ func (s *Server) withAuth(handler httprouter.Handle) httprouter.Handle {
|
|||||||
user := userFromJwtToken(r)
|
user := userFromJwtToken(r)
|
||||||
if user == "" {
|
if user == "" {
|
||||||
user = "anonymous"
|
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)
|
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) {
|
func (s *Server) GetDevices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
user := r.Context().Value("user")
|
user := r.Context().Value("user")
|
||||||
if user != ps.ByName("user") {
|
log.Debug(user)
|
||||||
log.WithField("user", user).WithField("path", r.URL.Path).Warn("Unauthorized access")
|
err := json.NewEncoder(w).Encode(s.Config)
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
if err != nil {
|
||||||
return
|
log.Error(err)
|
||||||
}
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
err := json.NewEncoder(w).Encode(s.config)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
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