This commit is contained in:
Ioannis Dressos 2023-10-30 18:40:24 +00:00 committed by GitHub
commit fa905d5f22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 250 additions and 129 deletions

View file

@ -1,4 +1,4 @@
![](https://github.com/ngoduykhanh/wireguard-ui/workflows/wireguard-ui%20build%20release/badge.svg)
![](https://github.com/idressos/wireguard-ui/workflows/wireguard-ui%20build%20release/badge.svg)
# wireguard-ui
@ -53,7 +53,11 @@ docker-compose up
| `WGUI_TABLE` | The default WireGuard table value settings | `auto` |
| `WGUI_CONFIG_FILE_PATH` | The default WireGuard config file path used in global settings | `/etc/wireguard/wg0.conf` |
| `WGUI_LOG_LEVEL` | The default log level. Possible values: `DEBUG`, `INFO`, `WARN`, `ERROR`, `OFF` | `INFO` |
| `WG_CONF_TEMPLATE` | The custom `wg.conf` config file template. Please refer to our [default template](https://github.com/ngoduykhanh/wireguard-ui/blob/master/templates/wg.conf) | N/A |
| `WGUI_BRAND_TEXT` | The brand text of the web application | `WireGuard UI` |
| `WGUI_ACCENT_COLOR` | The color of the interface sidebar | `#343a40` |
| `WGUI_LOGO_FILE_PATH` | The file path of the website logo | Embedded WireGuard logo |
| `WGUI_PAGE_TITLE_PREFIX` | The HTML title prefix for all pages | N/A |
| `WG_CONF_TEMPLATE` | The custom `wg.conf` config file template. Please refer to our [default template](https://github.com/idressos/wireguard-ui/blob/master/templates/wg.conf) | N/A |
| `EMAIL_FROM_ADDRESS` | The sender email address | N/A |
| `EMAIL_FROM_NAME` | The sender name | `WireGuard UI` |
| `SENDGRID_API_KEY` | The SendGrid api key | N/A |
@ -63,6 +67,7 @@ docker-compose up
| `SMTP_PASSWORD` | The SMTP user password | N/A |
| `SMTP_AUTH_TYPE` | The SMTP authentication type. Possible values: `PLAIN`, `LOGIN`, `NONE` | `NONE` |
| `SMTP_ENCRYPTION` | the encryption method. Possible values: `NONE`, `SSL`, `SSLTLS`, `TLS`, `STARTTLS` | `STARTTLS` |
| `HELLO_HOSTNAME` | Hostname to use for the hello message. smtp-relay.gmail.com needs this set to anything but `localhost` | `localhost` |
### Defaults for server configuration
@ -181,9 +186,9 @@ rc-update add wgui default
### Using Docker
Set `WGUI_MANAGE_RESTART=true` to manage Wireguard interface restarts.
Using `WGUI_MANAGE_START=true` can also replace the function of `wg-quick@wg0` service, to start Wireguard at boot, by
running the container with `restart: unless-stopped`. These settings can also pick up changes to Wireguard Config File
Set `WGUI_MANAGE_RESTART=true` to manage WireGuard interface restarts.
Using `WGUI_MANAGE_START=true` can also replace the function of `wg-quick@wg0` service, to start WireGuard at boot, by
running the container with `restart: unless-stopped`. These settings can also pick up changes to WireGuard Config File
Path, after restarting the container. Please make sure you have `--cap-add=NET_ADMIN` in your container config to make
this
feature work.
@ -224,7 +229,7 @@ go build -o wireguard-ui
## License
MIT. See [LICENSE](https://github.com/ngoduykhanh/wireguard-ui/blob/master/LICENSE).
MIT. See [LICENSE](https://github.com/idressos/wireguard-ui/blob/master/LICENSE).
## Support

BIN
custom/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -13,6 +13,7 @@ type SmtpMail struct {
port int
username string
password string
helloHostName string
authType mail.AuthType
encryption mail.Encryption
noTLSCheck bool
@ -46,8 +47,8 @@ func encryptionType(encryptionType string) mail.Encryption {
}
}
func NewSmtpMail(hostname string, port int, username string, password string, noTLSCheck bool, auth string, fromName, from string, encryption string) *SmtpMail {
ans := SmtpMail{hostname: hostname, port: port, username: username, password: password, noTLSCheck: noTLSCheck, fromName: fromName, from: from, authType: authType(auth), encryption: encryptionType(encryption)}
func NewSmtpMail(hostname string, port int, username string, password string, helloHostName string, noTLSCheck bool, auth string, fromName, from string, encryption string) *SmtpMail {
ans := SmtpMail{hostname: hostname, port: port, username: username, password: password, helloHostName: helloHostName, noTLSCheck: noTLSCheck, fromName: fromName, from: from, authType: authType(auth), encryption: encryptionType(encryption)}
return &ans
}
@ -66,6 +67,7 @@ func (o *SmtpMail) Send(toName string, to string, subject string, content string
server.Authentication = o.authType
server.Username = o.username
server.Password = o.password
server.Helo = o.helloHostName
server.Encryption = o.encryption
server.KeepAlive = false
server.ConnectTimeout = 10 * time.Second

View file

@ -2,7 +2,7 @@
### Kernel Module
Depending on if the Wireguard kernel module is available on your system you have more or less choices which example to use.
Depending on if the WireGuard kernel module is available on your system you have more or less choices which example to use.
You can check if the kernel modules are available via the following command:
```shell
@ -21,10 +21,10 @@ For security reasons it's highly recommended to change them before the first sta
## Examples
- **[system](system.yml)**
If you have Wireguard already installed on your system and only want to run the UI in docker this might fit the most.
If you have WireGuard already installed on your system and only want to run the UI in docker this might fit the most.
- **[linuxserver](linuxserver.yml)**
If you have the Wireguard kernel modules installed (included in the mainline kernel since version 5.6) but want it running inside of docker, this might fit the most.
If you have the WireGuard kernel modules installed (included in the mainline kernel since version 5.6) but want it running inside of docker, this might fit the most.
- **[boringtun](boringtun.yml)**
If Wireguard kernel modules are not available, you can switch to an userspace implementation like [boringtun](https://github.com/cloudflare/boringtun).
If WireGuard kernel modules are not available, you can switch to an userspace implementation like [boringtun](https://github.com/cloudflare/boringtun).

View file

@ -2,6 +2,7 @@ package handler
import (
"crypto/subtle"
"path/filepath"
"encoding/base64"
"encoding/json"
"fmt"
@ -42,6 +43,15 @@ func Favicon() echo.HandlerFunc {
}
}
func Logo() echo.HandlerFunc {
return func(c echo.Context) error {
if logo, ok := os.LookupEnv(util.LogoFilePathEnvVar); ok {
return c.File(logo)
}
return c.Redirect(http.StatusFound, util.BasePath+"/static/custom/img/logo.png")
}
}
// LoginPage handler
func LoginPage() echo.HandlerFunc {
return func(c echo.Context) error {
@ -337,7 +347,7 @@ func WireGuardClients(db store.IStore) echo.HandlerFunc {
}
}
// GetClients handler return a JSON list of Wireguard client data
// GetClients handler return a JSON list of WireGuard client data
func GetClients(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error {
@ -352,7 +362,7 @@ func GetClients(db store.IStore) echo.HandlerFunc {
}
}
// GetClient handler returns a JSON object of Wireguard client data
// GetClient handler returns a JSON object of WireGuard client data
func GetClient(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error {
@ -409,12 +419,12 @@ func NewClient(db store.IStore) echo.HandlerFunc {
guid := xid.New()
client.ID = guid.String()
// gen Wireguard key pair
// gen WireGuard key pair
if client.PublicKey == "" {
key, err := wgtypes.GeneratePrivateKey()
if err != nil {
log.Error("Cannot generate wireguard key pair: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate Wireguard key pair"})
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate WireGuard key pair"})
}
client.PrivateKey = key.String()
client.PublicKey = key.PublicKey().String()
@ -422,7 +432,7 @@ func NewClient(db store.IStore) echo.HandlerFunc {
_, err := wgtypes.ParseKey(client.PublicKey)
if err != nil {
log.Error("Cannot verify wireguard public key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify Wireguard public key"})
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify WireGuard public key"})
}
// check for duplicates
clients, err := db.GetClients(false)
@ -444,7 +454,7 @@ func NewClient(db store.IStore) echo.HandlerFunc {
if err != nil {
log.Error("Cannot generated preshared key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{
false, "Cannot generate Wireguard preshared key",
false, "Cannot generate WireGuard preshared key",
})
}
client.PresharedKey = presharedKey.String()
@ -455,7 +465,7 @@ func NewClient(db store.IStore) echo.HandlerFunc {
_, err := wgtypes.ParseKey(client.PresharedKey)
if err != nil {
log.Error("Cannot verify wireguard preshared key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify Wireguard preshared key"})
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify WireGuard preshared key"})
}
}
client.CreatedAt = time.Now().UTC()
@ -567,12 +577,12 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Extra Allowed IPs must be in CIDR format"})
}
// update Wireguard Client PublicKey
// update WireGuard Client PublicKey
if client.PublicKey != _client.PublicKey && _client.PublicKey != "" {
_, err := wgtypes.ParseKey(_client.PublicKey)
if err != nil {
log.Error("Cannot verify provided Wireguard public key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided Wireguard public key"})
log.Error("Cannot verify provided WireGuard public key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided WireGuard public key"})
}
// check for duplicates
clients, err := db.GetClients(false)
@ -587,7 +597,7 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
}
}
// When replacing any PublicKey, discard any locally stored Wireguard Client PrivateKey
// When replacing any PublicKey, discard any locally stored WireGuard Client PrivateKey
// Client PubKey no longer corresponds to locally stored PrivKey.
// QR code (needs PrivateKey) for this client is no longer possible now.
@ -597,12 +607,12 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
}
// update Wireguard Client PresharedKey
// update WireGuard Client PresharedKey
if client.PresharedKey != _client.PresharedKey && _client.PresharedKey != "" {
_, err := wgtypes.ParseKey(_client.PresharedKey)
if err != nil {
log.Error("Cannot verify provided Wireguard preshared key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided Wireguard preshared key"})
log.Error("Cannot verify provided WireGuard preshared key: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot verify provided WireGuard preshared key"})
}
}
@ -614,6 +624,7 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
client.AllocatedIPs = _client.AllocatedIPs
client.AllowedIPs = _client.AllowedIPs
client.ExtraAllowedIPs = _client.ExtraAllowedIPs
client.Endpoint = _client.Endpoint
client.PublicKey = _client.PublicKey
client.PresharedKey = _client.PresharedKey
client.UpdatedAt = time.Now().UTC()
@ -689,7 +700,7 @@ func DownloadClient(db store.IStore) echo.HandlerFunc {
// set response header for downloading
c.Response().Header().Set(echo.HeaderContentDisposition, fmt.Sprintf("attachment; filename=%s.conf", clientData.Client.Name))
return c.Stream(http.StatusOK, "text/plain", reader)
return c.Stream(http.StatusOK, "text/conf", reader)
}
}
@ -759,11 +770,11 @@ func WireGuardServerInterfaces(db store.IStore) echo.HandlerFunc {
func WireGuardServerKeyPair(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error {
// gen Wireguard key pair
// gen WireGuard key pair
key, err := wgtypes.GeneratePrivateKey()
if err != nil {
log.Error("Cannot generate wireguard key pair: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate Wireguard key pair"})
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate WireGuard key pair"})
}
var serverKeyPair model.ServerKeypair
@ -772,7 +783,7 @@ func WireGuardServerKeyPair(db store.IStore) echo.HandlerFunc {
serverKeyPair.UpdatedAt = time.Now().UTC()
if err := db.SaveServerKeyPair(serverKeyPair); err != nil {
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate Wireguard key pair"})
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate WireGuard key pair"})
}
log.Infof("Updated wireguard server interfaces settings: %v", serverKeyPair)
@ -796,6 +807,16 @@ func GlobalSettings(db store.IStore) echo.HandlerFunc {
}
}
func extractDeviceNameFromConfigPath(db store.IStore) string {
settings, err := db.GetGlobalSettings()
if err != nil {
log.Error("Cannot get global settings: ", err)
}
base := filepath.Base(settings.ConfigFilePath)
return strings.TrimSuffix(base, filepath.Ext(base))
}
// Status handler
func Status(db store.IStore) echo.HandlerFunc {
type PeerVM struct {
@ -826,6 +847,8 @@ func Status(db store.IStore) echo.HandlerFunc {
})
}
deviceName := extractDeviceNameFromConfigPath(db)
devices, err := wgClient.Devices()
if err != nil {
return c.Render(http.StatusInternalServerError, "status.html", map[string]interface{}{
@ -854,35 +877,37 @@ func Status(db store.IStore) echo.HandlerFunc {
conv := map[bool]int{true: 1, false: 0}
for i := range devices {
devVm := DeviceVM{Name: devices[i].Name}
for j := range devices[i].Peers {
var allocatedIPs string
for _, ip := range devices[i].Peers[j].AllowedIPs {
if len(allocatedIPs) > 0 {
allocatedIPs += "</br>"
if devices[i].Name == deviceName {
devVm := DeviceVM{Name: devices[i].Name}
for j := range devices[i].Peers {
var allocatedIPs string
for _, ip := range devices[i].Peers[j].AllowedIPs {
if len(allocatedIPs) > 0 {
allocatedIPs += "</br>"
}
allocatedIPs += ip.String()
}
allocatedIPs += ip.String()
}
pVm := PeerVM{
PublicKey: devices[i].Peers[j].PublicKey.String(),
ReceivedBytes: devices[i].Peers[j].ReceiveBytes,
TransmitBytes: devices[i].Peers[j].TransmitBytes,
LastHandshakeTime: devices[i].Peers[j].LastHandshakeTime,
LastHandshakeRel: time.Since(devices[i].Peers[j].LastHandshakeTime),
AllocatedIP: allocatedIPs,
Endpoint: devices[i].Peers[j].Endpoint.String(),
}
pVm.Connected = pVm.LastHandshakeRel.Minutes() < 3.
pVm := PeerVM{
PublicKey: devices[i].Peers[j].PublicKey.String(),
ReceivedBytes: devices[i].Peers[j].ReceiveBytes,
TransmitBytes: devices[i].Peers[j].TransmitBytes,
LastHandshakeTime: devices[i].Peers[j].LastHandshakeTime,
LastHandshakeRel: time.Since(devices[i].Peers[j].LastHandshakeTime),
AllocatedIP: allocatedIPs,
Endpoint: devices[i].Peers[j].Endpoint.String(),
}
pVm.Connected = pVm.LastHandshakeRel.Minutes() < 3.
if _client, ok := m[pVm.PublicKey]; ok {
pVm.Name = _client.Name
pVm.Email = _client.Email
if _client, ok := m[pVm.PublicKey]; ok {
pVm.Name = _client.Name
pVm.Email = _client.Email
}
devVm.Peers = append(devVm.Peers, pVm)
}
devVm.Peers = append(devVm.Peers, pVm)
sort.SliceStable(devVm.Peers, func(i, j int) bool { return devVm.Peers[i].Name < devVm.Peers[j].Name })
sort.SliceStable(devVm.Peers, func(i, j int) bool { return conv[devVm.Peers[i].Connected] > conv[devVm.Peers[j].Connected] })
devicesVm = append(devicesVm, devVm)
}
sort.SliceStable(devVm.Peers, func(i, j int) bool { return devVm.Peers[i].Name < devVm.Peers[j].Name })
sort.SliceStable(devVm.Peers, func(i, j int) bool { return conv[devVm.Peers[i].Connected] > conv[devVm.Peers[j].Connected] })
devicesVm = append(devicesVm, devVm)
}
}
@ -911,7 +936,7 @@ func GlobalSettingSubmit(db store.IStore) echo.HandlerFunc {
// write config to the database
if err := db.SaveGlobalSettings(globalSettings); err != nil {
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate Wireguard key pair"})
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot generate WireGuard key pair"})
}
log.Infof("Updated global settings: %v", globalSettings)
@ -985,7 +1010,7 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc {
}
}
// ApplyServerConfig handler to write config file and restart Wireguard server
// ApplyServerConfig handler to write config file and restart WireGuard server
func ApplyServerConfig(db store.IStore, tmplDir fs.FS) echo.HandlerFunc {
return func(c echo.Context) error {

34
main.go
View file

@ -30,6 +30,7 @@ var (
flagBindAddress string = "0.0.0.0:5000"
flagSmtpHostname string = "127.0.0.1"
flagSmtpPort int = 25
flagHelloHostName string = "localhost"
flagSmtpUsername string
flagSmtpPassword string
flagSmtpAuthType string = "NONE"
@ -41,14 +42,18 @@ var (
flagSessionSecret string = util.RandomString(32)
flagWgConfTemplate string
flagBasePath string
flagBrandText string = "WireGuard UI"
flagAccentColor string = "#343a40"
flagPageTitlePrefix string
)
const (
defaultEmailSubject = "Your wireguard configuration"
defaultEmailContent = `Hi,</br>
<p>In this email you can find your personal configuration for our wireguard server.</p>
defaultEmailSubject = "Your VPN configuration"
<p>Best</p>
defaultEmailContent = `
<p>Greetings,</p>
<p>Please find attached your personal configuration for our VPN server.<br>You may find instructions on how to install the WireGuard VPN client <a href="https://www.wireguard.com/install/">here</a>.</p>
<p>Best regards.</p>
`
)
@ -69,6 +74,7 @@ func init() {
flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.")
flag.StringVar(&flagSmtpHostname, "smtp-hostname", util.LookupEnvOrString("SMTP_HOSTNAME", flagSmtpHostname), "SMTP Hostname")
flag.IntVar(&flagSmtpPort, "smtp-port", util.LookupEnvOrInt("SMTP_PORT", flagSmtpPort), "SMTP Port")
flag.StringVar(&flagHelloHostName, "hello-hostname", util.LookupEnvOrString("HELLO_HOSTNAME", flagHelloHostName), "Hello HostName")
flag.StringVar(&flagSmtpUsername, "smtp-username", util.LookupEnvOrString("SMTP_USERNAME", flagSmtpUsername), "SMTP Username")
flag.StringVar(&flagSmtpPassword, "smtp-password", util.LookupEnvOrString("SMTP_PASSWORD", flagSmtpPassword), "SMTP Password")
flag.BoolVar(&flagSmtpNoTLSCheck, "smtp-no-tls-check", util.LookupEnvOrBool("SMTP_NO_TLS_CHECK", flagSmtpNoTLSCheck), "Disable TLS verification for SMTP. This is potentially dangerous.")
@ -80,6 +86,10 @@ func init() {
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(&flagBasePath, "base-path", util.LookupEnvOrString("BASE_PATH", flagBasePath), "The base path of the URL")
flag.StringVar(&flagBrandText, "brand-text", util.LookupEnvOrString("WGUI_BRAND_TEXT", flagBrandText), "The UI brand text or name")
flag.StringVar(&flagAccentColor, "accent-color", util.LookupEnvOrString("WGUI_ACCENT_COLOR", flagAccentColor), "The UI accent color")
flag.StringVar(&flagPageTitlePrefix, "page-title-prefix", util.LookupEnvOrString("WGUI_PAGE_TITLE_PREFIX", flagPageTitlePrefix), "The prefix of the page title")
flag.Parse()
// update runtime config
@ -87,6 +97,7 @@ func init() {
util.BindAddress = flagBindAddress
util.SmtpHostname = flagSmtpHostname
util.SmtpPort = flagSmtpPort
util.HelloHostName = flagHelloHostName
util.SmtpUsername = flagSmtpUsername
util.SmtpPassword = flagSmtpPassword
util.SmtpAuthType = flagSmtpAuthType
@ -98,16 +109,19 @@ func init() {
util.SessionSecret = []byte(flagSessionSecret)
util.WgConfTemplate = flagWgConfTemplate
util.BasePath = util.ParseBasePath(flagBasePath)
util.BrandText = flagBrandText
util.AccentColor = flagAccentColor
util.PageTitlePrefix = flagPageTitlePrefix
// print only if log level is INFO or lower
if lvl, _ := util.ParseLogLevel(util.LookupEnvOrString(util.LogLevel, "INFO")); lvl <= log.INFO {
// print app information
fmt.Println("Wireguard UI")
fmt.Println("WireGuard UI")
fmt.Println("App Version\t:", appVersion)
fmt.Println("Git Commit\t:", gitCommit)
fmt.Println("Git Ref\t\t:", gitRef)
fmt.Println("Build Time\t:", buildTime)
fmt.Println("Git Repo\t:", "https://github.com/ngoduykhanh/wireguard-ui")
fmt.Println("Git Repo\t:", "https://github.com/idressos/wireguard-ui")
fmt.Println("Authentication\t:", !util.DisableLogin)
fmt.Println("Bind address\t:", util.BindAddress)
//fmt.Println("Sendgrid key\t:", util.SendgridApiKey)
@ -133,6 +147,9 @@ func main() {
extraData["gitCommit"] = gitCommit
extraData["basePath"] = util.BasePath
extraData["loginDisabled"] = flagDisableLogin
extraData["brandText"] = flagBrandText;
extraData["accentColor"] = flagAccentColor;
extraData["pageTitlePrefix"] = flagPageTitlePrefix;
// strip the "templates/" prefix from the embedded directory so files can be read by their direct name (e.g.
// "base.html" instead of "templates/base.html")
@ -163,13 +180,14 @@ func main() {
if util.SendgridApiKey != "" {
sendmail = emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom)
} else {
sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom, util.SmtpEncryption)
sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.HelloHostName, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom, util.SmtpEncryption)
}
app.GET(util.BasePath+"/test-hash", handler.GetHashesChanges(db), handler.ValidSession)
app.GET(util.BasePath+"/about", handler.AboutPage())
app.GET(util.BasePath+"/_health", handler.Health())
app.GET(util.BasePath+"/favicon", handler.Favicon())
app.GET(util.BasePath+"/logo", handler.Logo())
app.POST(util.BasePath+"/new-client", handler.NewClient(db), handler.ValidSession, handler.ContentTypeJson)
app.POST(util.BasePath+"/update-client", handler.UpdateClient(db), handler.ValidSession, handler.ContentTypeJson)
app.POST(util.BasePath+"/email-client", handler.EmailClient(db, sendmail, defaultEmailSubject, defaultEmailContent), handler.ValidSession, handler.ContentTypeJson)

View file

@ -15,6 +15,7 @@ type Client struct {
AllocatedIPs []string `json:"allocated_ips"`
AllowedIPs []string `json:"allowed_ips"`
ExtraAllowedIPs []string `json:"extra_allowed_ips"`
Endpoint string `json:"endpoint"`
UseServerDNS bool `json:"use_server_dns"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`

View file

@ -1,7 +1,7 @@
{
"name": "wireguard-ui",
"version": "1.0.0",
"description": "Wireguard web interface",
"description": "WireGuard web interface",
"main": "index.js",
"repository": "git@github.com:ngoduykhanh/wireguard-ui.git",
"author": "Khanh Ngo <k@ndk.name>",

View file

@ -68,7 +68,10 @@ func (o *JsonDB) Init() error {
serverInterface.PostDown = util.LookupEnvOrString(util.ServerPostDownScriptEnvVar, "")
serverInterface.UpdatedAt = time.Now().UTC()
o.conn.Write("server", "interfaces", serverInterface)
os.Chmod(serverInterfacePath, 0600)
err := util.ManagePerms(serverInterfacePath)
if err != nil {
return err
}
}
// server's key pair
@ -83,7 +86,10 @@ func (o *JsonDB) Init() error {
serverKeyPair.PublicKey = key.PublicKey().String()
serverKeyPair.UpdatedAt = time.Now().UTC()
o.conn.Write("server", "keypair", serverKeyPair)
os.Chmod(serverKeyPairPath, 0600)
err = util.ManagePerms(serverKeyPairPath)
if err != nil {
return err
}
}
// global settings
@ -108,7 +114,10 @@ func (o *JsonDB) Init() error {
globalSetting.ConfigFilePath = util.LookupEnvOrString(util.ConfigFilePathEnvVar, util.DefaultConfigFilePath)
globalSetting.UpdatedAt = time.Now().UTC()
o.conn.Write("server", "global_settings", globalSetting)
os.Chmod(globalSettingPath, 0600)
err := util.ManagePerms(globalSettingPath)
if err != nil {
return err
}
}
// hashes
@ -117,7 +126,10 @@ func (o *JsonDB) Init() error {
clientServerHashes.Client = "none"
clientServerHashes.Server = "none"
o.conn.Write("server", "hashes", clientServerHashes)
os.Chmod(hashesPath, 0600)
err := util.ManagePerms(hashesPath)
if err != nil {
return err
}
}
// user info
@ -136,7 +148,10 @@ func (o *JsonDB) Init() error {
user.PasswordHash = hash
}
o.conn.Write("users", user.Username, user)
os.Chmod(path.Join(path.Join(o.dbPath, "users"), user.Username+".json"), 0600)
err = util.ManagePerms(path.Join(path.Join(o.dbPath, "users"), user.Username+".json"))
if err != nil {
return err
}
}
return nil
@ -182,7 +197,10 @@ func (o *JsonDB) GetUserByName(username string) (model.User, error) {
func (o *JsonDB) SaveUser(user model.User) error {
userPath := path.Join(path.Join(o.dbPath, "users"), user.Username+".json")
output := o.conn.Write("users", user.Username, user)
os.Chmod(userPath, 0600)
err := util.ManagePerms(userPath)
if err != nil {
return err
}
return output
}
@ -295,7 +313,10 @@ func (o *JsonDB) GetClientByID(clientID string, qrCodeSettings model.QRCodeSetti
func (o *JsonDB) SaveClient(client model.Client) error {
clientPath := path.Join(path.Join(o.dbPath, "clients"), client.ID+".json")
output := o.conn.Write("clients", client.ID, client)
os.Chmod(clientPath, 0600)
err := util.ManagePerms(clientPath)
if err != nil {
return err
}
return output
}
@ -306,21 +327,30 @@ func (o *JsonDB) DeleteClient(clientID string) error {
func (o *JsonDB) SaveServerInterface(serverInterface model.ServerInterface) error {
serverInterfacePath := path.Join(path.Join(o.dbPath, "server"), "interfaces.json")
output := o.conn.Write("server", "interfaces", serverInterface)
os.Chmod(serverInterfacePath, 0600)
err := util.ManagePerms(serverInterfacePath)
if err != nil {
return err
}
return output
}
func (o *JsonDB) SaveServerKeyPair(serverKeyPair model.ServerKeypair) error {
serverKeyPairPath := path.Join(path.Join(o.dbPath, "server"), "keypair.json")
output := o.conn.Write("server", "keypair", serverKeyPair)
os.Chmod(serverKeyPairPath, 0600)
err := util.ManagePerms(serverKeyPairPath)
if err != nil {
return err
}
return output
}
func (o *JsonDB) SaveGlobalSettings(globalSettings model.GlobalSetting) error {
globalSettingsPath := path.Join(path.Join(o.dbPath, "server"), "global_settings.json")
output := o.conn.Write("server", "global_settings", globalSettings)
os.Chmod(globalSettingsPath, 0600)
err := util.ManagePerms(globalSettingsPath)
if err != nil {
return err
}
return output
}
@ -336,6 +366,9 @@ func (o *JsonDB) GetHashes() (model.ClientServerHashes, error) {
func (o *JsonDB) SaveHashes(hashes model.ClientServerHashes) error {
hashesPath := path.Join(path.Join(o.dbPath, "server"), "hashes.json")
output := o.conn.Write("server", "hashes", hashes)
os.Chmod(hashesPath, 0600)
err := util.ManagePerms(hashesPath)
if err != nil {
return err
}
return output
}
}

View file

@ -3,10 +3,10 @@ package jsondb
import (
"encoding/json"
"fmt"
"os"
"path"
"github.com/ngoduykhanh/wireguard-ui/model"
"github.com/ngoduykhanh/wireguard-ui/util"
)
func (o *JsonDB) GetWakeOnLanHosts() ([]model.WakeOnLanHost, error) {
@ -70,7 +70,11 @@ func (o *JsonDB) SaveWakeOnLanHost(host model.WakeOnLanHost) error {
wakeOnLanHostPath := path.Join(path.Join(o.dbPath, model.WakeOnLanHostCollectionName), resourceName+".json")
output := o.conn.Write(model.WakeOnLanHostCollectionName, resourceName, host)
os.Chmod(wakeOnLanHostPath, 0600)
err = util.ManagePerms(wakeOnLanHostPath)
if err != nil {
return err
}
return output
}

View file

@ -22,7 +22,7 @@ About
<div class="col-md-6">
<div class="card card-success">
<div class="card-header">
<h3 class="card-title">About Wireguard-UI</h3>
<h3 class="card-title">About WireGuard-UI</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
@ -63,7 +63,7 @@ About
</div>
<strong>Copyright &copy;
<script>document.write(new Date().getFullYear())</script>
<a href="https://github.com/ngoduykhanh/wireguard-ui">Wireguard UI</a>.
<a href="https://github.com/idressos/wireguard-ui">WireGuard UI</a>.
</strong> All rights reserved.
</div>
@ -83,7 +83,7 @@ About
$.ajax({
cache: false,
method: 'GET',
url: 'https://api.github.com/repos/ngoduykhanh/wireguard-ui/releases/tags/' + $("#version").val(),
url: 'https://api.github.com/repos/idressos/wireguard-ui/releases/tags/' + $("#version").val(),
dataType: 'json',
contentType: "application/json",
success: function (data) {
@ -99,7 +99,7 @@ About
$.ajax({
cache: false,
method: 'GET',
url: 'https://api.github.com/repos/ngoduykhanh/wireguard-ui/releases/latest',
url: 'https://api.github.com/repos/idressos/wireguard-ui/releases/latest',
dataType: 'json',
contentType: "application/json",
success: function (data) {
@ -121,7 +121,7 @@ About
$.ajax({
cache: false,
method: 'GET',
url: 'https://api.github.com/repos/ngoduykhanh/wireguard-ui/contributors',
url: 'https://api.github.com/repos/idressos/wireguard-ui/contributors',
dataType: 'json',
contentType: "application/json",
success: function (data) {

View file

@ -5,7 +5,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>{{template "title" .}}</title>
<title>{{.pageTitlePrefix}}{{template "title" .}}</title>
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Favicon -->
@ -84,10 +84,10 @@
<!-- /.navbar -->
<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-primary elevation-4">
<aside class="main-sidebar sidebar-dark-primary elevation-4" style="background-color: {{.accentColor}};">
<!-- Brand Logo -->
<a href="{{.basePath}}" class="brand-link">
<span class="brand-text">&nbsp; WIREGUARD UI</span>
<span class="brand-text">&nbsp; {{.brandText}}</span>
</a>
<!-- Sidebar -->
@ -120,7 +120,7 @@
<a href="{{.basePath}}/" class="nav-link {{if eq .baseData.Active ""}}active{{end}}">
<i class="nav-icon fas fa-user-secret"></i>
<p>
Wireguard Clients
Clients
</p>
</a>
</li>
@ -130,7 +130,7 @@
<a href="{{.basePath}}/wg-server" class="nav-link {{if eq .baseData.Active "wg-server" }}active{{end}}">
<i class="nav-icon fas fa-server"></i>
<p>
Wireguard Server
WireGuard Server
</p>
</a>
</li>
@ -174,6 +174,8 @@
</p>
</a>
</li>
{{if .baseData.Admin}}
<li class="nav-header">ABOUT</li>
<li class="nav-item">
<a href="{{.basePath}}/about" class="nav-link {{if eq .baseData.Active "about" }}active{{end}}">
@ -183,6 +185,7 @@
</p>
</a>
</li>
{{end}}
</ul>
</nav>
<!-- /.sidebar-menu -->
@ -194,7 +197,7 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">New Wireguard Client</h4>
<h4 class="modal-title">New WireGuard Client</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
@ -232,6 +235,10 @@
</label>
<input type="text" data-role="tagsinput" class="form-control" id="client_extra_allowed_ips" value="{{ StringsJoin .client_defaults.ExtraAllowedIps "," }}">
</div>
<div class="form-group">
<label for="client_endpoint" class="control-label">Endpoint</label>
<input type="text" class="form-control" id="client_endpoint" name="client_endpoint">
</div>
<div class="form-group">
<div class="icheck-primary d-inline">
<input type="checkbox" id="use_server_dns" {{ if .client_defaults.UseServerDNS }}checked{{ end }}>
@ -328,7 +335,7 @@
<div class="float-right d-none d-sm-block">
<b>Version</b> {{ .appVersion }}
</div>
<strong>Copyright &copy; <script>document.write(new Date().getFullYear())</script> <a href="https://github.com/ngoduykhanh/wireguard-ui">Wireguard UI</a>.</strong> All rights
<strong>Copyright &copy; <script>document.write(new Date().getFullYear())</script> <a href="https://github.com/idressos/wireguard-ui">WireGuard UI</a>.</strong> All rights
reserved.
</footer>
-->
@ -413,6 +420,7 @@
const email = $("#client_email").val();
const allocated_ips = $("#client_allocated_ips").val().split(",");
const allowed_ips = $("#client_allowed_ips").val().split(",");
const endpoint = $("#client_endpoint").val();
let use_server_dns = false;
let extra_allowed_ips = [];
@ -434,7 +442,7 @@
const preshared_key = $("#client_preshared_key").val();
const data = {"name": name, "email": email, "allocated_ips": allocated_ips, "allowed_ips": allowed_ips,
"extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled,
"extra_allowed_ips": extra_allowed_ips, "endpoint": endpoint, "use_server_dns": use_server_dns, "enabled": enabled,
"public_key": public_key, "preshared_key": preshared_key};
$.ajax({

View file

@ -1,5 +1,5 @@
{{define "title"}}
Wireguard Clients
Clients
{{end}}
{{define "top_css"}}
@ -17,13 +17,13 @@ Wireguard Clients
{{end}}
{{define "page_title"}}
Wireguard Clients
Clients
{{end}}
{{define "page_content"}}
<section class="content">
<div class="container-fluid">
<!-- <h5 class="mt-4 mb-2">Wireguard Clients</h5> -->
<!-- <h5 class="mt-4 mb-2">Clients</h5> -->
<div class="row" id="client-list">
</div>
<!-- /.row -->
@ -113,6 +113,10 @@ Wireguard Clients
<input type="text" data-role="tagsinput" class="form-control"
id="_client_extra_allowed_ips">
</div>
<div class="form-group">
<label for="_client_endpoint" class="control-label">Endpoint</label>
<input type="text" class="form-control" id="_client_endpoint" name="client_endpoint">
</div>
<div class="form-group">
<div class="icheck-primary d-inline">
<input type="checkbox" id="_use_server_dns">
@ -477,6 +481,8 @@ Wireguard Clients
modal.find("#_client_extra_allowed_ips").addTag(obj);
});
modal.find("#_client_endpoint").val(client.endpoint);
modal.find("#_use_server_dns").prop("checked", client.use_server_dns);
modal.find("#_enabled").prop("checked", client.enabled);
@ -564,6 +570,8 @@ Wireguard Clients
extra_allowed_ips = $("#_client_extra_allowed_ips").val().split(",");
}
const endpoint = $("#_client_endpoint").val();
if ($("#_use_server_dns").is(':checked')){
use_server_dns = true;
}
@ -575,7 +583,8 @@ Wireguard Clients
}
const data = {"id": client_id, "name": name, "email": email, "allocated_ips": allocated_ips,
"allowed_ips": allowed_ips, "extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled, "public_key": public_key, "preshared_key": preshared_key};
"allowed_ips": allowed_ips, "extra_allowed_ips": extra_allowed_ips, "endpoint": endpoint,
"use_server_dns": use_server_dns, "enabled": enabled, "public_key": public_key, "preshared_key": preshared_key};
$.ajax({
cache: false,

View file

@ -22,7 +22,7 @@ Global Settings
<div class="col-md-6">
<div class="card card-success">
<div class="card-header">
<h3 class="card-title">Wireguard Global Settings</h3>
<h3 class="card-title">WireGuard Global Settings</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
@ -68,7 +68,7 @@ Global Settings
value="{{ .globalSettings.Table }}">
</div>
<div class="form-group">
<label for="config_file_path">Wireguard Config File Path</label>
<label for="config_file_path">WireGuard Config File Path</label>
<input type="text" class="form-control" id="config_file_path"
name="config_file_path" placeholder="E.g. /etc/wireguard/wg0.conf"
value="{{ .globalSettings.ConfigFilePath }}">
@ -92,7 +92,7 @@ Global Settings
<div class="card-body">
<dl>
<dt>1. Endpoint Address</dt>
<dd>The public IP address of your Wireguard server that the client will connect to. Click on
<dd>The public IP address of your WireGuard server that the client will connect to. Click on
<strong>Suggest</strong> button to auto detect the public IP address of your server.</dd>
<dt>2. DNS Servers</dt>
<dd>The DNS servers will be set to client config.</dd>
@ -110,8 +110,8 @@ Global Settings
<dd>Add a matching <code>fwmark</code> on all packets going out of a WireGuard non-default-route tunnel. Default value: <code>0xca6c</code></dd>
<dt>6. Table</dt>
<dd>Value for the <code>Table</code> setting in the wg conf file. Default value: <code>auto</code></dd>
<dt>7. Wireguard Config File Path</dt>
<dd>The path of your Wireguard server config file. Please make sure the parent directory
<dt>7. WireGuard Config File Path</dt>
<dd>The path of your WireGuard server config file. Please make sure the parent directory
exists and is writable.</dd>
</dl>
</div>
@ -195,7 +195,7 @@ Global Settings
}
</script>
<script>
// Wireguard Interface DNS server tag input
// WireGuard Interface DNS server tag input
$("#dns_servers").tagsInput({
'width': '100%',
'height': '75%',

View file

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>WireGuard UI</title>
<title>{{.brandText}}</title>
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Favicon -->
@ -24,8 +24,8 @@
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<a href="https://github.com/ngoduykhanh/wireguard-ui">WireGuard UI</a>
<div class="login-logo pb-3">
<img class="img-fluid" src="{{.basePath}}/logo">
</div>
<!-- /.login-logo -->
<div class="card">

View file

@ -1,5 +1,5 @@
{{define "title"}}
Wireguard Server
WireGuard Server
{{end}}
{{define "top_css"}}
@ -10,13 +10,13 @@ Wireguard Server
{{end}}
{{define "page_title"}}
Wireguard Server Settings
WireGuard Server Settings
{{end}}
{{define "page_content"}}
<section class="content">
<div class="container-fluid">
<!-- <h5 class="mt-4 mb-2">Wireguard Server</h5> -->
<!-- <h5 class="mt-4 mb-2">WireGuard Server</h5> -->
<div class="row">
<!-- left column -->
<div class="col-md-6">
@ -39,13 +39,13 @@ Wireguard Server Settings
</div>
<div class="form-group">
<label for="post_up">Post Up Script</label>
<input type="text" class="form-control" id="post_up" name="post_up"
placeholder="Post Up Script" value="{{ .serverInterface.PostUp }}">
<textarea class="form-control" id="post_up" name="post_up"
placeholder="Post Up Script">{{ .serverInterface.PostUp }}</textarea>
</div>
<div class="form-group">
<label for="post_down">Post Down Script</label>
<input type="text" class="form-control" id="post_down" name="post_down"
placeholder="Post Down Script" value="{{ .serverInterface.PostDown }}">
<textarea class="form-control" id="post_down" name="post_down"
placeholder="Post Down Script">{{ .serverInterface.PostDown }}</textarea>
</div>
</div>
<!-- /.card-body -->
@ -109,7 +109,7 @@ Wireguard Server Settings
</button>
</div>
<div class="modal-body">
<p>Are you sure to generate a new key pair for the Wireguard server?<br/>
<p>Are you sure to generate a new key pair for the WireGuard server?<br/>
The existing Client's peer public key need to be updated to keep the connection working.</p>
</div>
<div class="modal-footer justify-content-between">
@ -142,7 +142,7 @@ Wireguard Server Settings
data: JSON.stringify(data),
success: function(data) {
$("#modal_new_client").modal('hide');
toastr.success('Updated Wireguard server interface addresses successfully');
toastr.success('Updated WireGuard server interface addresses successfully');
},
error: function(jqXHR, exception) {
const responseJson = jQuery.parseJSON(jqXHR.responseText);
@ -152,7 +152,7 @@ Wireguard Server Settings
}
</script>
<script>
// Wireguard Interface Addresses tag input
// WireGuard Interface Addresses tag input
$("#addresses").tagsInput({
'width': '100%',
// 'height': '75%',
@ -169,7 +169,7 @@ Wireguard Server Settings
$("#addresses").addTag('{{.}}');
{{end}}
// Wireguard Interface Addresses form validation
// WireGuard Interface Addresses form validation
$(document).ready(function () {
$.validator.setDefaults({
submitHandler: function () {
@ -205,7 +205,7 @@ Wireguard Server Settings
});
});
// Wireguard Key Pair generation confirmation button
// WireGuard Key Pair generation confirmation button
$(document).ready(function () {
$("#btn_generate_confirm").click(function () {
$.ajax({

View file

@ -35,7 +35,6 @@ Connected Peers
{{ end}}
{{ range $dev := .devices }}
<table class="table table-sm">
<caption>List of connected peers for device with name {{ $dev.Name }} </caption>
<thead>
<tr>
<th scope="col">#</th>

View file

@ -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/idressos/wireguard-ui)
# Please don't modify it manually, otherwise your change might get replaced.
# Address updated at: {{ .serverConfig.Interface.UpdatedAt }}
@ -7,10 +7,11 @@
Address = {{$first :=true}}{{range .serverConfig.Interface.Addresses }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
ListenPort = {{ .serverConfig.Interface.ListenPort }}
PrivateKey = {{ .serverConfig.KeyPair.PrivateKey }}
{{if .globalSettings.FirewallMark }}FwMark = {{ .globalSettings.FirewallMark }}{{end}}
{{if .globalSettings.MTU}}MTU = {{ .globalSettings.MTU }}{{end}}
PostUp = {{ .serverConfig.Interface.PostUp }}
PostDown = {{ .serverConfig.Interface.PostDown }}
Table = {{ .globalSettings.Table }}
{{if .serverConfig.Interface.PostUp }}PostUp = {{ .serverConfig.Interface.PostUp }}{{end}}
{{if .serverConfig.Interface.PostDown }}PostDown = {{ .serverConfig.Interface.PostDown }}{{end}}
{{if .globalSettings.Table}}Table = {{ .globalSettings.Table }}{{end}}
{{range .clientDataList}}{{if eq .Client.Enabled true}}
# ID: {{ .Client.ID }}
@ -20,6 +21,8 @@ Table = {{ .globalSettings.Table }}
# Update at: {{ .Client.UpdatedAt }}
[Peer]
PublicKey = {{ .Client.PublicKey }}
{{if .Client.PresharedKey }}PresharedKey = {{ .Client.PresharedKey }}
{{end}}AllowedIPs = {{$first :=true}}{{range .Client.AllocatedIPs }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}{{range .Client.ExtraAllowedIPs }},{{.}}{{end}}
{{end}}{{end}}
{{if .Client.PresharedKey }}PresharedKey = {{ .Client.PresharedKey }}{{end}}
AllowedIPs = {{$first :=true}}{{range .Client.AllocatedIPs }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}{{range .Client.ExtraAllowedIPs }},{{.}}{{end}}{{end}}
{{if $.globalSettings.PersistentKeepalive}}PersistentKeepalive = {{ $.globalSettings.PersistentKeepalive }}{{end}}
{{if .Client.Endpoint }}Endpoint = {{ .Client.Endpoint }}{{end}}
{{end}}

View file

@ -10,6 +10,7 @@ var (
SmtpPort int
SmtpUsername string
SmtpPassword string
HelloHostName string
SmtpNoTLSCheck bool
SmtpEncryption string
SmtpAuthType string
@ -19,6 +20,9 @@ var (
SessionSecret []byte
WgConfTemplate string
BasePath string
BrandText string
AccentColor string
PageTitlePrefix string
)
const (
@ -53,6 +57,10 @@ const (
DefaultClientExtraAllowedIpsEnvVar = "WGUI_DEFAULT_CLIENT_EXTRA_ALLOWED_IPS"
DefaultClientUseServerDNSEnvVar = "WGUI_DEFAULT_CLIENT_USE_SERVER_DNS"
DefaultClientEnableAfterCreationEnvVar = "WGUI_DEFAULT_CLIENT_ENABLE_AFTER_CREATION"
BrandTextEnvVar = "WGUI_BRAND_TEXT"
AccentColorEnvVar = "WGUI_ACCENT_COLOR"
PageTitlePrefixEnvVar = "WGUI_PAGE_TITLE_PREFIX"
LogoFilePathEnvVar = "WGUI_LOGO_FILE_PATH"
)
func ParseBasePath(basePath string) string {

View file

@ -4,8 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/ngoduykhanh/wireguard-ui/store"
"golang.org/x/mod/sumdb/dirhash"
"io"
"io/fs"
"io/ioutil"
@ -19,6 +17,9 @@ import (
"text/template"
"time"
"github.com/ngoduykhanh/wireguard-ui/store"
"golang.org/x/mod/sumdb/dirhash"
externalip "github.com/glendc/go-external-ip"
"github.com/labstack/gommon/log"
"github.com/ngoduykhanh/wireguard-ui/model"
@ -382,7 +383,7 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip
return true, nil
}
// WriteWireGuardServerConfig to write Wireguard server config. e.g. wg0.conf
// WriteWireGuardServerConfig to write WireGuard server config. e.g. wg0.conf
func WriteWireGuardServerConfig(tmplDir fs.FS, serverConfig model.Server, clientDataList []model.ClientData, usersList []model.User, globalSettings model.GlobalSetting) error {
var tmplWireguardConf string
@ -540,3 +541,8 @@ func RandomString(length int) string {
}
return string(b)
}
func ManagePerms(path string) error {
err := os.Chmod(path, 0600)
return err
}