mirror of
https://github.com/ngoduykhanh/wireguard-ui.git
synced 2025-06-07 00:46:58 +03:00
commit
f302990116
18 changed files with 80 additions and 56 deletions
|
@ -1,4 +1,4 @@
|
||||||

|

|
||||||
|
|
||||||
# wireguard-ui
|
# wireguard-ui
|
||||||
|
|
||||||
|
@ -27,8 +27,9 @@ Download the binary file from the release page and run it directly on the host m
|
||||||
|
|
||||||
### Using docker compose
|
### Using docker compose
|
||||||
|
|
||||||
The [examples/docker-compose](examples/docker-compose) folder contains example docker-compose files.
|
You can take a look at this example
|
||||||
Choose the example which fits you the most, adjust the configuration for your needs, then run it like below:
|
of [docker-compose.yml](https://github.com/alikhanich/wireguard-ui/blob/master/docker-compose.yaml). Please adjust
|
||||||
|
volume mount points to work with your setup. Then run it like below:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker-compose up
|
docker-compose up
|
||||||
|
@ -218,7 +219,7 @@ go build -o wireguard-ui
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT. See [LICENSE](https://github.com/ngoduykhanh/wireguard-ui/blob/master/LICENSE).
|
MIT. See [LICENSE](https://github.com/alikhanich/wireguard-ui/blob/master/LICENSE).
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
|
|
@ -3,21 +3,18 @@ version: "3"
|
||||||
services:
|
services:
|
||||||
wg:
|
wg:
|
||||||
build: .
|
build: .
|
||||||
#image: ngoduykhanh/wireguard-ui:latest
|
image: wg-ui:latest
|
||||||
container_name: wgui
|
container_name: wgui
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
- SENDGRID_API_KEY
|
- SESSION_SECRET=vnsjdvb9134f39hvn9249
|
||||||
- EMAIL_FROM_ADDRESS
|
|
||||||
- EMAIL_FROM_NAME
|
|
||||||
- SESSION_SECRET
|
|
||||||
- WGUI_USERNAME=alpha
|
- WGUI_USERNAME=alpha
|
||||||
- WGUI_PASSWORD=this-unusual-password
|
- WGUI_PASSWORD=Negjqgfhjkm1!
|
||||||
- WG_CONF_TEMPLATE
|
|
||||||
- WGUI_MANAGE_START=false
|
- WGUI_MANAGE_START=false
|
||||||
- WGUI_MANAGE_RESTART=false
|
- WGUI_MANAGE_RESTART=false
|
||||||
|
- WGUI_API_KEY=test
|
||||||
logging:
|
logging:
|
||||||
driver: json-file
|
driver: json-file
|
||||||
options:
|
options:
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module github.com/ngoduykhanh/wireguard-ui
|
module github.com/alikhanich/wireguard-ui
|
||||||
|
|
||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@ import (
|
||||||
"golang.zx2c4.com/wireguard/wgctrl"
|
"golang.zx2c4.com/wireguard/wgctrl"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/ngoduykhanh/wireguard-ui/emailer"
|
"github.com/alikhanich/wireguard-ui/emailer"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/model"
|
"github.com/alikhanich/wireguard-ui/model"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/store"
|
"github.com/alikhanich/wireguard-ui/store"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/util"
|
"github.com/alikhanich/wireguard-ui/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Health check handler
|
// Health check handler
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/model"
|
"github.com/alikhanich/wireguard-ui/model"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/store"
|
"github.com/alikhanich/wireguard-ui/store"
|
||||||
"github.com/sabhiram/go-wol/wol"
|
"github.com/sabhiram/go-wol/wol"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/labstack/echo-contrib/session"
|
"github.com/labstack/echo-contrib/session"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/util"
|
"github.com/alikhanich/wireguard-ui/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ValidSession(next echo.HandlerFunc) echo.HandlerFunc {
|
func ValidSession(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
@ -38,6 +38,10 @@ func isValidSession(c echo.Context) bool {
|
||||||
}
|
}
|
||||||
sess, _ := session.Get("session", c)
|
sess, _ := session.Get("session", c)
|
||||||
cookie, err := c.Cookie("session_token")
|
cookie, err := c.Cookie("session_token")
|
||||||
|
apiKey, ok := sess.Values["api_key"].(string)
|
||||||
|
if ok && apiKey != util.ApiKey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if err != nil || sess.Values["session_token"] != cookie.Value {
|
if err != nil || sess.Values["session_token"] != cookie.Value {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
50
main.go
50
main.go
|
@ -11,12 +11,12 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/emailer"
|
"github.com/alikhanich/wireguard-ui/emailer"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/handler"
|
"github.com/alikhanich/wireguard-ui/handler"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/router"
|
"github.com/alikhanich/wireguard-ui/router"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/store/jsondb"
|
"github.com/alikhanich/wireguard-ui/store/jsondb"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/util"
|
"github.com/alikhanich/wireguard-ui/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -41,6 +41,7 @@ var (
|
||||||
flagSessionSecret string
|
flagSessionSecret string
|
||||||
flagWgConfTemplate string
|
flagWgConfTemplate string
|
||||||
flagBasePath string
|
flagBasePath string
|
||||||
|
flagApiKey string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -80,6 +81,7 @@ func init() {
|
||||||
flag.StringVar(&flagSessionSecret, "session-secret", util.LookupEnvOrString("SESSION_SECRET", flagSessionSecret), "The key used to encrypt session cookies.")
|
flag.StringVar(&flagSessionSecret, "session-secret", util.LookupEnvOrString("SESSION_SECRET", flagSessionSecret), "The key used to encrypt session cookies.")
|
||||||
flag.StringVar(&flagWgConfTemplate, "wg-conf-template", util.LookupEnvOrString("WG_CONF_TEMPLATE", flagWgConfTemplate), "Path to custom wg.conf template.")
|
flag.StringVar(&flagWgConfTemplate, "wg-conf-template", util.LookupEnvOrString("WG_CONF_TEMPLATE", flagWgConfTemplate), "Path to custom wg.conf template.")
|
||||||
flag.StringVar(&flagBasePath, "base-path", util.LookupEnvOrString("BASE_PATH", flagBasePath), "The base path of the URL")
|
flag.StringVar(&flagBasePath, "base-path", util.LookupEnvOrString("BASE_PATH", flagBasePath), "The base path of the URL")
|
||||||
|
flag.StringVar(&flagApiKey, "api-key", util.LookupEnvOrString("WGUI_API_KEY", ""), "Specify API key for auth")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// update runtime config
|
// update runtime config
|
||||||
|
@ -98,27 +100,25 @@ func init() {
|
||||||
util.SessionSecret = []byte(flagSessionSecret)
|
util.SessionSecret = []byte(flagSessionSecret)
|
||||||
util.WgConfTemplate = flagWgConfTemplate
|
util.WgConfTemplate = flagWgConfTemplate
|
||||||
util.BasePath = util.ParseBasePath(flagBasePath)
|
util.BasePath = util.ParseBasePath(flagBasePath)
|
||||||
|
util.ApiKey = flagApiKey
|
||||||
// print only if log level is INFO or lower
|
// print app information
|
||||||
if lvl, _ := util.ParseLogLevel(util.LookupEnvOrString(util.LogLevel, "INFO")); lvl <= log.INFO {
|
fmt.Println("Wireguard UI")
|
||||||
// print app information
|
fmt.Println("App Version\t:", appVersion)
|
||||||
fmt.Println("Wireguard UI")
|
fmt.Println("Git Commit\t:", gitCommit)
|
||||||
fmt.Println("App Version\t:", appVersion)
|
fmt.Println("Git Ref\t\t:", gitRef)
|
||||||
fmt.Println("Git Commit\t:", gitCommit)
|
fmt.Println("Build Time\t:", buildTime)
|
||||||
fmt.Println("Git Ref\t\t:", gitRef)
|
fmt.Println("Git Repo\t:", "https://github.com/alikhanich/wireguard-ui")
|
||||||
fmt.Println("Build Time\t:", buildTime)
|
fmt.Println("Authentication\t:", !util.DisableLogin)
|
||||||
fmt.Println("Git Repo\t:", "https://github.com/ngoduykhanh/wireguard-ui")
|
fmt.Println("Bind address\t:", util.BindAddress)
|
||||||
fmt.Println("Authentication\t:", !util.DisableLogin)
|
//fmt.Println("Sendgrid key\t:", util.SendgridApiKey)
|
||||||
fmt.Println("Bind address\t:", util.BindAddress)
|
fmt.Println("Email from\t:", util.EmailFrom)
|
||||||
//fmt.Println("Sendgrid key\t:", util.SendgridApiKey)
|
fmt.Println("Email from name\t:", util.EmailFromName)
|
||||||
fmt.Println("Email from\t:", util.EmailFrom)
|
//fmt.Println("Session secret\t:", util.SessionSecret)
|
||||||
fmt.Println("Email from name\t:", util.EmailFromName)
|
fmt.Println("Custom wg.conf\t:", util.WgConfTemplate)
|
||||||
//fmt.Println("Session secret\t:", util.SessionSecret)
|
fmt.Println("Base path\t:", util.BasePath+"/")
|
||||||
fmt.Println("Custom wg.conf\t:", util.WgConfTemplate)
|
|
||||||
fmt.Println("Base path\t:", util.BasePath+"/")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db, err := jsondb.New("./db")
|
db, err := jsondb.New("./db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/util"
|
"github.com/alikhanich/wireguard-ui/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateRegistry is a custom html/template renderer for Echo framework
|
// TemplateRegistry is a custom html/template renderer for Echo framework
|
||||||
|
@ -47,11 +47,31 @@ func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c
|
||||||
return tmpl.ExecuteTemplate(w, "base.html", data)
|
return tmpl.ExecuteTemplate(w, "base.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func apiKeyMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
apiKey := c.Request().Header.Get("X-API-Key")
|
||||||
|
if apiKey == "" {
|
||||||
|
apiKey = c.QueryParam("api_key")
|
||||||
|
}
|
||||||
|
sess, err := session.Get("session", c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sess.Values["api_key"] = apiKey
|
||||||
|
err = sess.Save(c.Request(), c.Response())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
// New function
|
// New function
|
||||||
func New(tmplDir fs.FS, extraData map[string]string, secret []byte) *echo.Echo {
|
func New(tmplDir fs.FS, extraData map[string]string, secret []byte) *echo.Echo {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Use(session.Middleware(sessions.NewCookieStore(secret)))
|
|
||||||
|
|
||||||
|
store := sessions.NewCookieStore(secret)
|
||||||
|
e.Use(session.Middleware(store))
|
||||||
|
e.Use(apiKeyMiddleware)
|
||||||
// read html template file to string
|
// read html template file to string
|
||||||
tmplBaseString, err := util.StringFromEmbedFile(tmplDir, "base.html")
|
tmplBaseString, err := util.StringFromEmbedFile(tmplDir, "base.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/ngoduykhanh/wireguard-ui/model"
|
"github.com/alikhanich/wireguard-ui/model"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/util"
|
"github.com/alikhanich/wireguard-ui/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JsonDB struct {
|
type JsonDB struct {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package jsondb
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/model"
|
"github.com/alikhanich/wireguard-ui/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (o *JsonDB) GetWakeOnLanHosts() ([]model.WakeOnLanHost, error) {
|
func (o *JsonDB) GetWakeOnLanHosts() ([]model.WakeOnLanHost, error) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package store
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ngoduykhanh/wireguard-ui/model"
|
"github.com/alikhanich/wireguard-ui/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IStore interface {
|
type IStore interface {
|
||||||
|
|
|
@ -63,7 +63,7 @@ About
|
||||||
</div>
|
</div>
|
||||||
<strong>Copyright ©
|
<strong>Copyright ©
|
||||||
<script>document.write(new Date().getFullYear())</script>
|
<script>document.write(new Date().getFullYear())</script>
|
||||||
<a href="https://github.com/ngoduykhanh/wireguard-ui">Wireguard UI</a>.
|
<a href="https://github.com/alikhanich/wireguard-ui">Wireguard UI</a>.
|
||||||
</strong> All rights reserved.
|
</strong> All rights reserved.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -326,7 +326,7 @@
|
||||||
<div class="float-right d-none d-sm-block">
|
<div class="float-right d-none d-sm-block">
|
||||||
<b>Version</b> {{ .appVersion }}
|
<b>Version</b> {{ .appVersion }}
|
||||||
</div>
|
</div>
|
||||||
<strong>Copyright © <script>document.write(new Date().getFullYear())</script> <a href="https://github.com/ngoduykhanh/wireguard-ui">Wireguard UI</a>.</strong> All rights
|
<strong>Copyright © <script>document.write(new Date().getFullYear())</script> <a href="https://github.com/alikhanich/wireguard-ui">Wireguard UI</a>.</strong> All rights
|
||||||
reserved.
|
reserved.
|
||||||
</footer>
|
</footer>
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<body class="hold-transition login-page">
|
<body class="hold-transition login-page">
|
||||||
<div class="login-box">
|
<div class="login-box">
|
||||||
<div class="login-logo">
|
<div class="login-logo">
|
||||||
<a href="https://github.com/ngoduykhanh/wireguard-ui">WireGuard UI</a>
|
<a href="https://github.com/alikhanich/wireguard-ui">WireGuard UI</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.login-logo -->
|
<!-- /.login-logo -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{ range $idx, $host := .hosts }}
|
{{ range $idx, $host := .hosts }}
|
||||||
{{- /*gotype: github.com/ngoduykhanh/wireguard-ui/model.WakeOnLanHost*/ -}}
|
{{- /*gotype: github.com/alikhanich/wireguard-ui/model.WakeOnLanHost*/ -}}
|
||||||
<div class="col-sm-4" id="{{ $host.ResolveResourceName }}">
|
<div class="col-sm-4" id="{{ $host.ResolveResourceName }}">
|
||||||
<div class="info-box">
|
<div class="info-box">
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# This file was generated using wireguard-ui (https://github.com/ngoduykhanh/wireguard-ui)
|
# This file was generated using wireguard-ui (https://github.com/alikhanich/wireguard-ui)
|
||||||
# Please don't modify it manually, otherwise your change might get replaced.
|
# Please don't modify it manually, otherwise your change might get replaced.
|
||||||
|
|
||||||
# Address updated at: {{ .serverConfig.Interface.UpdatedAt }}
|
# Address updated at: {{ .serverConfig.Interface.UpdatedAt }}
|
||||||
|
|
|
@ -19,6 +19,7 @@ var (
|
||||||
SessionSecret []byte
|
SessionSecret []byte
|
||||||
WgConfTemplate string
|
WgConfTemplate string
|
||||||
BasePath string
|
BasePath string
|
||||||
|
ApiKey string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -51,6 +52,7 @@ const (
|
||||||
DefaultClientExtraAllowedIpsEnvVar = "WGUI_DEFAULT_CLIENT_EXTRA_ALLOWED_IPS"
|
DefaultClientExtraAllowedIpsEnvVar = "WGUI_DEFAULT_CLIENT_EXTRA_ALLOWED_IPS"
|
||||||
DefaultClientUseServerDNSEnvVar = "WGUI_DEFAULT_CLIENT_USE_SERVER_DNS"
|
DefaultClientUseServerDNSEnvVar = "WGUI_DEFAULT_CLIENT_USE_SERVER_DNS"
|
||||||
DefaultClientEnableAfterCreationEnvVar = "WGUI_DEFAULT_CLIENT_ENABLE_AFTER_CREATION"
|
DefaultClientEnableAfterCreationEnvVar = "WGUI_DEFAULT_CLIENT_ENABLE_AFTER_CREATION"
|
||||||
|
DefaultApiKeyEnvVar = "WGUI_API_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseBasePath(basePath string) string {
|
func ParseBasePath(basePath string) string {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
|
|
||||||
externalip "github.com/glendc/go-external-ip"
|
externalip "github.com/glendc/go-external-ip"
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"github.com/ngoduykhanh/wireguard-ui/model"
|
"github.com/alikhanich/wireguard-ui/model"
|
||||||
"github.com/sdomino/scribble"
|
"github.com/sdomino/scribble"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue