Initial implementation of wireguard configuration

This commit is contained in:
Daniel Lundin
2019-05-01 17:42:46 +02:00
parent 0663166bcb
commit 1cb07ee66b
6 changed files with 279 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
wireguard-ui
+13
View File
@@ -0,0 +1,13 @@
module github.com/embarkstudios/wireguard-ui
go 1.12
require (
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
github.com/mdlayher/wireguardctrl v0.0.0-20190419142446-a4a944b88a6b
github.com/sirupsen/logrus v1.4.1
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6
)
+38
View File
@@ -0,0 +1,38 @@
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mdlayher/genetlink v0.0.0-20190419142426-b806ce69960a h1:tIPUNU99ot2Tko8SorsytkeFC0to6pRJB6koxswpeB8=
github.com/mdlayher/genetlink v0.0.0-20190419142426-b806ce69960a/go.mod h1:J+g63IQCVwjKLOxodrxOylt23f7d5vVB9rgNh+T13Uk=
github.com/mdlayher/netlink v0.0.0-20190419142405-71c9566a34ae h1:Ec6B7pKh4YZyKI9VtTeZmN1GGLvAIT/fs2votDcWnMU=
github.com/mdlayher/netlink v0.0.0-20190419142405-71c9566a34ae/go.mod h1:TR9n0u8mie4+iszGTMjP6QRwUZQNynkhDbXTLF6DUi4=
github.com/mdlayher/wireguardctrl v0.0.0-20190419142446-a4a944b88a6b h1:3EhP8SsJHU7mbXm4iWtO57HR2LI48KaCuSfDhAywrBg=
github.com/mdlayher/wireguardctrl v0.0.0-20190419142446-a4a944b88a6b/go.mod h1:3oz/rt7iwoq/LQa+QaFheGKzGZvc+vlmaBvtxeh6Jtc=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba h1:h0zCzEL5UW1mERvwTN6AXcc75PpLkY6OcReia6Dq1BM=
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be h1:mI+jhqkn68ybP0ORJqunXn+fq+Eeb4hHKqLQcFICjAc=
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+38
View File
@@ -0,0 +1,38 @@
package main
import (
"strings"
log "github.com/sirupsen/logrus"
"gopkg.in/alecthomas/kingpin.v2"
)
var (
logLevel = kingpin.Flag("log-level", "The level of logging").Default("info").Enum("debug", "info", "warn", "error", "panic", "fatal")
)
func main() {
kingpin.HelpFlag.Short('h')
kingpin.CommandLine.DefaultEnvars()
kingpin.Parse()
switch strings.ToLower(*logLevel) {
case "debug":
log.SetLevel(log.DebugLevel)
case "warn":
log.SetLevel(log.WarnLevel)
case "error":
log.SetLevel(log.ErrorLevel)
case "panic":
log.SetLevel(log.PanicLevel)
default:
log.SetLevel(log.InfoLevel)
}
log.Info("Starting")
server := NewServer()
err := server.Start()
if err != nil {
log.Fatal(err)
}
}
+98
View File
@@ -0,0 +1,98 @@
package main
import (
"net/http"
"os"
"github.com/mdlayher/wireguardctrl"
"github.com/mdlayher/wireguardctrl/wgtypes"
log "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"gopkg.in/alecthomas/kingpin.v2"
)
var (
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
wgLinkName = kingpin.Flag("wg-device-name", "Wireguard network device name").Default("wg0").String()
wgListenPort = kingpin.Flag("wg-listen-port", "Wireguard UDP port to listen to").Default("51820").Int()
)
type Server struct {
mux *http.ServeMux
storage *Storage
config *ServerConfig
}
type WgLink struct {
attrs *netlink.LinkAttrs
}
func (w *WgLink) Attrs() *netlink.LinkAttrs {
return w.attrs
}
func (w *WgLink) Type() string {
return "wireguard"
}
func NewServer() *Server {
storage := NewStorage()
server := &Server{
mux: http.NewServeMux(),
storage: storage,
config: storage.GetServerConfig(),
}
server.mux.HandleFunc("/", server.Hello)
return server
}
func (s *Server) initInterface() error {
attrs := netlink.NewLinkAttrs()
attrs.Name = *wgLinkName
link := WgLink{
attrs: &attrs,
}
err := netlink.LinkAdd(&link)
if os.IsExist(err) {
log.Infof("Wireguard interface %s already exists. Reusing.", *wgLinkName)
} else if err != nil {
return err
}
wg, err := wireguardctrl.New()
if err != nil {
return err
}
key, err := wgtypes.ParseKey(s.config.PrivateKey)
if err != nil {
return err
}
cfg := wgtypes.Config{
PrivateKey: &key,
ListenPort: wgListenPort,
}
wg.ConfigureDevice(*wgLinkName, cfg)
return nil
}
func (s *Server) Start() error {
err := s.initInterface()
if err != nil {
return err
}
log.WithField("listenAddr", *listenAddr).Info("Starting server")
return http.ListenAndServe(*listenAddr, s.mux)
}
func (s *Server) Hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
}
+91
View File
@@ -0,0 +1,91 @@
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
}
type UserConfig struct {
Name string
Devices []DeviceConfig
}
type DeviceConfig struct {
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
}