Merge branch 'ngoduykhanh:master' into support-multi-subnet

This commit is contained in:
brittondodd 2022-01-09 13:03:05 -05:00 committed by GitHub
commit 655375258e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 204 additions and 99 deletions

64
.github/stale.yml vendored
View file

@ -1,19 +1,57 @@
# Number of days of inactivity before an issue becomes stale # Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 60 daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 7 daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels: # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
- pinned onlyLabels: []
- security
- enhancement # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
- feature request exemptLabels: []
# Label to use when marking an issue as stale
staleLabel: wontfix # Set to true to ignore issues in a project (defaults to false)
# Comment to post when marking an issue as stale. Set to `false` to disable exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: > markComment: >
This issue has been automatically marked as stale because it has not had This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you recent activity. It will be closed if no further activity occurs. Thank you
for your contributions. for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: true # Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
issues:
exemptLabels:
- enhancement
- feature request
- documentation
- bug

View file

@ -1,6 +1,10 @@
# Build stage # Build stage
FROM golang:1.16.7-alpine3.14 as builder FROM golang:1.16.7-alpine3.14 as builder
LABEL maintainer="Khanh Ngo <k@ndk.name" LABEL maintainer="Khanh Ngo <k@ndk.name"
ARG TARGETOS=linux
ARG TARGETARCH=amd64
ARG BUILD_DEPENDENCIES="npm \ ARG BUILD_DEPENDENCIES="npm \
yarn" yarn"
@ -44,7 +48,7 @@ RUN go mod download && \
# Build # Build
RUN rice embed-go && \ RUN rice embed-go && \
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o wg-ui . CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o wg-ui .
# Release stage # Release stage
FROM alpine:3.11 FROM alpine:3.11
@ -64,5 +68,5 @@ COPY --from=builder --chown=wgui:wgui /build/wg-ui /app
RUN chmod +x wg-ui RUN chmod +x wg-ui
EXPOSE 5000/tcp EXPOSE 5000/tcp
HEALTHCHECK CMD ["wget","--output-document=-","--quiet","--tries=1","http://127.0.0.1:5000/login"] HEALTHCHECK CMD ["wget","--output-document=-","--quiet","--tries=1","http://127.0.0.1:5000/_health"]
ENTRYPOINT ["./wg-ui"] ENTRYPOINT ["./wg-ui"]

2
Jenkinsfile vendored Normal file
View file

@ -0,0 +1,2 @@
@Library('ndk-jenkins-shared-libs')_
imageBuilder('wireguard-ui')

View file

@ -37,7 +37,7 @@ In order to sent the wireguard configuration to clients via email (using sendgri
``` ```
SENDGRID_API_KEY: Your sendgrid api key SENDGRID_API_KEY: Your sendgrid api key
EMAIL_FROM: the email address you registered on sendgrid EMAIL_FROM_ADDRESS: the email address you registered on sendgrid
EMAIL_FROM_NAME: the sender's email address EMAIL_FROM_NAME: the sender's email address
``` ```

View file

@ -27,17 +27,25 @@ function renderClientList(data) {
<img src="${obj.QRCode}" /> <img src="${obj.QRCode}" />
<div class="info-box-content"> <div class="info-box-content">
<div class="btn-group"> <div class="btn-group">
<button onclick="location.href='/download?clientid=${obj.Client.id}'" type="button" <a href="/download?clientid=${obj.Client.id}" class="btn btn-outline-success btn-sm">Download</a>
class="btn btn-outline-success btn-sm">Download</button> </div>
<button type="button" class="btn btn-outline-warning btn-sm" data-toggle="modal" <div class="btn-group">
<button type="button" class="btn btn-outline-secondary btn-sm" data-toggle="modal"
data-target="#modal_email_client" data-clientid="${obj.Client.id}" data-target="#modal_email_client" data-clientid="${obj.Client.id}"
data-clientname="${obj.Client.name}">Email</button> data-clientname="${obj.Client.name}">Email</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal" <button type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
data-target="#modal_edit_client" data-clientid="${obj.Client.id}" data-target="#modal_edit_client" data-clientid="${obj.Client.id}"
data-clientname="${obj.Client.name}">Edit</button> data-clientname="${obj.Client.name}">Edit</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-warning btn-sm" data-toggle="modal" <button type="button" class="btn btn-outline-warning btn-sm" data-toggle="modal"
data-target="#modal_pause_client" data-clientid="${obj.Client.id}" data-target="#modal_pause_client" data-clientid="${obj.Client.id}"
data-clientname="${obj.Client.name}">Disable</button> data-clientname="${obj.Client.name}">Disable</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal" <button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal"
data-target="#modal_remove_client" data-clientid="${obj.Client.id}" data-target="#modal_remove_client" data-clientid="${obj.Client.id}"
data-clientname="${obj.Client.name}">Remove</button> data-clientname="${obj.Client.name}">Remove</button>
@ -46,9 +54,9 @@ function renderClientList(data) {
<span class="info-box-text"><i class="fas fa-user"></i> ${obj.Client.name}</span> <span class="info-box-text"><i class="fas fa-user"></i> ${obj.Client.name}</span>
<span class="info-box-text"><i class="fas fa-envelope"></i> ${obj.Client.email}</span> <span class="info-box-text"><i class="fas fa-envelope"></i> ${obj.Client.email}</span>
<span class="info-box-text"><i class="fas fa-clock"></i> <span class="info-box-text"><i class="fas fa-clock"></i>
${obj.Client.created_at}</span> ${prettyDateTime(obj.Client.created_at)}</span>
<span class="info-box-text"><i class="fas fa-history"></i> <span class="info-box-text"><i class="fas fa-history"></i>
${obj.Client.updated_at}</span> ${prettyDateTime(obj.Client.updated_at)}</span>
<span class="info-box-text"><i class="fas fa-server" style="${obj.Client.use_server_dns ? "opacity: 1.0" : "opacity: 0.5"}"></i> <span class="info-box-text"><i class="fas fa-server" style="${obj.Client.use_server_dns ? "opacity: 1.0" : "opacity: 0.5"}"></i>
${obj.Client.use_server_dns ? 'DNS enabled' : 'DNS disabled'}</span> ${obj.Client.use_server_dns ? 'DNS enabled' : 'DNS disabled'}</span>
<span class="info-box-text"><strong>IP Allocation</strong></span>` <span class="info-box-text"><strong>IP Allocation</strong></span>`
@ -63,3 +71,10 @@ function renderClientList(data) {
$('#client-list').append(html); $('#client-list').append(html);
}); });
} }
function prettyDateTime(timeStr) {
const dt = new Date(timeStr);
const offsetMs = dt.getTimezoneOffset() * 60 * 1000;
const dateLocal = new Date(dt.getTime() - offsetMs);
return dateLocal.toISOString().slice(0, 19).replace(/-/g, "/").replace("T", " ");
}

View file

@ -10,7 +10,7 @@ services:
network_mode: host network_mode: host
environment: environment:
- SENDGRID_API_KEY - SENDGRID_API_KEY
- EMAIL_FROM - EMAIL_FROM_ADDRESS
- EMAIL_FROM_NAME - EMAIL_FROM_NAME
- SESSION_SECRET - SESSION_SECRET
- WGUI_USERNAME=alpha - WGUI_USERNAME=alpha

View file

@ -24,6 +24,13 @@ import (
"github.com/ngoduykhanh/wireguard-ui/util" "github.com/ngoduykhanh/wireguard-ui/util"
) )
// Health check handler
func Health() echo.HandlerFunc {
return func(c echo.Context) error {
return c.String(http.StatusOK, "ok")
}
}
// LoginPage handler // LoginPage handler
func LoginPage() echo.HandlerFunc { func LoginPage() echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
@ -346,7 +353,7 @@ func DownloadClient(db store.IStore) echo.HandlerFunc {
reader := strings.NewReader(config) reader := strings.NewReader(config)
// set response header for downloading // set response header for downloading
c.Response().Header().Set(echo.HeaderContentDisposition, "attachment; filename=wg0.conf") 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/plain", reader)
} }
} }
@ -621,7 +628,11 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc {
fmt.Sprintf("Cannot suggest ip allocation: failed to get available ip from network %s", cidr), fmt.Sprintf("Cannot suggest ip allocation: failed to get available ip from network %s", cidr),
}) })
} }
suggestedIPs = append(suggestedIPs, fmt.Sprintf("%s/32", ip)) if (strings.Contains(ip, ":")) {
suggestedIPs = append(suggestedIPs, fmt.Sprintf("%s/128", ip))
} else {
suggestedIPs = append(suggestedIPs, fmt.Sprintf("%s/32", ip))
}
} }
return c.JSON(http.StatusOK, suggestedIPs) return c.JSON(http.StatusOK, suggestedIPs)

View file

@ -34,7 +34,7 @@ var (
const ( const (
defaultEmailSubject = "Your wireguard configuration" defaultEmailSubject = "Your wireguard configuration"
defaultEmailContent = `Hi,</br> defaultEmailContent = `Hi,</br>
<p>in this email you can file your personal configuration for our wireguard server.</p> <p>In this email you can find your personal configuration for our wireguard server.</p>
<p>Best</p> <p>Best</p>
` `
@ -43,6 +43,7 @@ const (
func init() { func init() {
// command-line flags and env variables // command-line flags and env variables
flag.BoolVar(&flagDisableLogin, "disable-login", util.LookupEnvOrBool("DISABLE_LOGIN", flagDisableLogin), "Disable authentication on the app. This is potentially dangerous.")
flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.") flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.")
flag.StringVar(&flagSendgridApiKey, "sendgrid-api-key", util.LookupEnvOrString("SENDGRID_API_KEY", flagSendgridApiKey), "Your sendgrid api key.") flag.StringVar(&flagSendgridApiKey, "sendgrid-api-key", util.LookupEnvOrString("SENDGRID_API_KEY", flagSendgridApiKey), "Your sendgrid api key.")
flag.StringVar(&flagEmailFrom, "email-from", util.LookupEnvOrString("EMAIL_FROM_ADDRESS", flagEmailFrom), "'From' email address.") flag.StringVar(&flagEmailFrom, "email-from", util.LookupEnvOrString("EMAIL_FROM_ADDRESS", flagEmailFrom), "'From' email address.")
@ -104,6 +105,7 @@ func main() {
sendmail := emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom) sendmail := emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom)
app.GET("/_health", handler.Health())
app.GET("/logout", handler.Logout(), handler.ValidSession) app.GET("/logout", handler.Logout(), handler.ValidSession)
app.POST("/new-client", handler.NewClient(db), handler.ValidSession) app.POST("/new-client", handler.NewClient(db), handler.ValidSession)
app.POST("/update-client", handler.UpdateClient(db), handler.ValidSession) app.POST("/update-client", handler.UpdateClient(db), handler.ValidSession)

View file

@ -4,7 +4,9 @@ set -e
DIR=$(dirname "$0") DIR=$(dirname "$0")
# install node modules # install node modules
yarn install --pure-lockfile --production YARN=yarn
[ -x /usr/bin/lsb_release ] && [ -n "`lsb_release -i | grep Debian`" ] && YARN=yarnpkg
$YARN install --pure-lockfile --production
# Copy admin-lte dist # Copy admin-lte dist
mkdir -p "${DIR}/assets/dist/js" "${DIR}/assets/dist/css" && \ mkdir -p "${DIR}/assets/dist/js" "${DIR}/assets/dist/css" && \

View file

@ -44,17 +44,17 @@
</ul> </ul>
<!-- SEARCH FORM --> <!-- SEARCH FORM -->
<form class="form-inline ml-3"> <!-- <form class="form-inline ml-3">-->
<div class="input-group input-group-sm"> <!-- <div class="input-group input-group-sm">-->
<input class="form-control form-control-navbar" type="search" placeholder="Search" <!-- <input class="form-control form-control-navbar" type="search" placeholder="Search"-->
aria-label="Search"> <!-- aria-label="Search">-->
<div class="input-group-append"> <!-- <div class="input-group-append">-->
<button class="btn btn-navbar" type="submit"> <!-- <button class="btn btn-navbar" type="submit">-->
<i class="fas fa-search"></i> <!-- <i class="fas fa-search"></i>-->
</button> <!-- </button>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
</form> <!-- </form>-->
<!-- Right navbar links --> <!-- Right navbar links -->
<div class="navbar-nav ml-auto"> <div class="navbar-nav ml-auto">
@ -238,7 +238,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 &copy; 2020 <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/ngoduykhanh/wireguard-ui">Wireguard UI</a>.</strong> All rights
reserved. reserved.
</footer> </footer>
@ -388,19 +388,11 @@
client_name: { client_name: {
required: true, required: true,
}, },
client_email: {
required: true,
email: true,
},
}, },
messages: { messages: {
client_name: { client_name: {
required: "Please enter a name" required: "Please enter a name"
}, },
client_email: {
required: "Please enter an email address",
email: "Please enter a valid email address"
},
}, },
errorElement: 'span', errorElement: 'span',
errorPlacement: function (error, element) { errorPlacement: function (error, element) {

View file

@ -44,7 +44,7 @@ Wireguard Clients
<input type="hidden" id="e_client_id" name="e_client_id"> <input type="hidden" id="e_client_id" name="e_client_id">
<div class="form-group"> <div class="form-group">
<label for="e_client_email" class="control-label">Email</label> <label for="e_client_email" class="control-label">Email</label>
<input type="text" class="form-control" id="e_client_email" name="client_email"> <input type="text" class="form-control" id="e_client_email" name="e_client_email">
</div> </div>
</div> </div>
<div class="modal-footer justify-content-between"> <div class="modal-footer justify-content-between">
@ -447,50 +447,40 @@ Wireguard Clients
} }
}); });
// Edit client form validation // Edit client form validation
$("#frm_edit_client").validate({ $("#frm_edit_client").validate({
rules: {
client_name: {
required: true,
},
client_email: {
required: true,
email: true,
},
},
messages: {
client_name: {
required: "Please enter a name"
},
client_email: {
required: "Please enter an email address",
email: "Please enter a valid email address"
},
},
errorElement: 'span',
errorPlacement: function (error, element) {
error.addClass('invalid-feedback');
element.closest('.form-group').append(error);
},
highlight: function (element, errorClass, validClass) {
$(element).addClass('is-invalid');
},
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass('is-invalid');
}
});
// Email client form validation
$("#frm_email_client").validate({
rules: { rules: {
client_email: { client_name: {
required: true,
},
},
messages: {
client_name: {
required: "Please enter a name"
},
},
errorElement: 'span',
errorPlacement: function (error, element) {
error.addClass('invalid-feedback');
element.closest('.form-group').append(error);
},
highlight: function (element, errorClass, validClass) {
$(element).addClass('is-invalid');
},
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass('is-invalid');
}
});
// Email client form validation
$("#frm_email_client").validate({
rules: {
e_client_email: {
required: true, required: true,
email: true, email: true,
}, },
}, },
messages: { messages: {
client_email: { e_client_email: {
required: "Please enter an email address", required: "Please enter an email"
email: "Please enter a valid email address"
}, },
}, },
errorElement: 'span', errorElement: 'span',

View file

@ -47,13 +47,13 @@ Global Settings
<div class="form-group"> <div class="form-group">
<label for="mtu">MTU</label> <label for="mtu">MTU</label>
<input type="text" class="form-control" id="mtu" name="mtu" placeholder="MTU" <input type="text" class="form-control" id="mtu" name="mtu" placeholder="MTU"
value="{{ .globalSettings.MTU }}"> value="{{if .globalSettings.MTU}}{{ .globalSettings.MTU }}{{end}}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="persistent_keepalive">Persistent Keepalive</label> <label for="persistent_keepalive">Persistent Keepalive</label>
<input type="text" class="form-control" id="persistent_keepalive" <input type="text" class="form-control" id="persistent_keepalive"
name="persistent_keepalive" placeholder="Persistent Keepalive" name="persistent_keepalive" placeholder="Persistent Keepalive"
value="{{ .globalSettings.PersistentKeepalive }}"> value="{{if .globalSettings.PersistentKeepalive }}{{ .globalSettings.PersistentKeepalive }}{{end}}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="config_file_path">Wireguard Config File Path</label> <label for="config_file_path">Wireguard Config File Path</label>
@ -71,6 +71,37 @@ Global Settings
</div> </div>
<!-- /.card --> <!-- /.card -->
</div> </div>
<div class="col-md-6">
<div class="card card-success">
<div class="card-header">
<h3 class="card-title">Help</h3>
</div>
<!-- /.card-header -->
<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
<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>
<dt>3. MTU</dt>
<dd>The MTU will be set to server config. By default it is <code>1420</code>. You might want
to adjust the MTU size if your connection (e.g PPPoE, 3G, satellite network, etc) has a low MTU.</dd>
<dd>Leave blank to omit this setting in the Server config.</dd>
<dt>4. Persistent Keepalive</dt>
<dd>By default, WireGuard peers remain silent while they do not need to communicate,
so peers located behind a NAT and/or firewall may be unreachable from other peers
until they reach out to other peers themselves. Adding <code>PersistentKeepalive</code>
can ensure that the connection remains open.</dd>
<dd>Leave blank to omit this setting in the Client config.</dd>
<dt>5. 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>
</div>
<!-- /.card -->
</div>
</div> </div>
<!-- /.row --> <!-- /.row -->
</div> </div>
@ -172,12 +203,10 @@ Global Settings
$("#frm_global_settings").validate({ $("#frm_global_settings").validate({
rules: { rules: {
mtu: { mtu: {
required: true,
digits: true, digits: true,
range: [68, 65535] range: [68, 65535]
}, },
persistent_keepalive: { persistent_keepalive: {
required: true,
digits: true digits: true
}, },
config_file_path: { config_file_path: {
@ -186,12 +215,10 @@ Global Settings
}, },
messages: { messages: {
mtu: { mtu: {
required: "Please enter a MTU value",
digits: "MTU must be an integer", digits: "MTU must be an integer",
range: "MTU must be in range 68..65535" range: "MTU must be in range 68..65535"
}, },
persistent_keepalive: { persistent_keepalive: {
required: "Please enter a Persistent Keepalive value",
digits: "Persistent keepalive must be an integer" digits: "Persistent keepalive must be an integer"
}, },
config_file_path: { config_file_path: {

View file

@ -57,7 +57,7 @@
</div> </div>
<!-- /.col --> <!-- /.col -->
<div class="col-4"> <div class="col-4">
<button id="btn_login" type="button" class="btn btn-primary btn-block">Sign In</button> <button id="btn_login" type="submit" class="btn btn-primary btn-block">Sign In</button>
</div> </div>
<!-- /.col --> <!-- /.col -->
</div> </div>
@ -91,6 +91,11 @@
</script> </script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$('form').on('submit', function(e) {
e.preventDefault();
$("#btn_login").trigger('click');
});
$("#btn_login").click(function () { $("#btn_login").click(function () {
const username = $("#username").val(); const username = $("#username").val();
const password = $("#password").val(); const password = $("#password").val();

View file

@ -14,6 +14,20 @@ Connected Peers
{{end}} {{end}}
{{define "page_content"}} {{define "page_content"}}
<script>
function bytesToHumanReadable(temporal) {
const units = [" ", " K", " M", " G", " T", " P", " E", " Z", " Y"]
let pow = 0
while (temporal > 1024) {
temporal /= 1024
pow ++
if (pow == units.length-1) break
}
return parseFloat(temporal.toFixed(3)) + units[pow]+"Bytes"
}
</script>
<section class="content"> <section class="content">
<div class="container-fluid"> <div class="container-fluid">
{{ if .error }} {{ if .error }}
@ -41,8 +55,8 @@ Connected Peers
<td>{{ $peer.Name }}</td> <td>{{ $peer.Name }}</td>
<td>{{ $peer.Email }}</td> <td>{{ $peer.Email }}</td>
<td>{{ $peer.PublicKey }}</td> <td>{{ $peer.PublicKey }}</td>
<td>{{ $peer.ReceivedBytes }}</td> <td title="{{ $peer.ReceivedBytes }} Bytes"><script>document.write(bytesToHumanReadable({{ $peer.ReceivedBytes }}))</script></td>
<td>{{ $peer.TransmitBytes }}</td> <td title="{{ $peer.TransmitBytes }} Bytes"><script>document.write(bytesToHumanReadable({{ $peer.TransmitBytes }}))</script></td>
<td>{{ $peer.Connected }}</td> <td>{{ $peer.Connected }}</td>
<td>{{ $peer.LastHandshakeTime }}</td> <td>{{ $peer.LastHandshakeTime }}</td>
</tr> </tr>

View file

@ -1,5 +1,5 @@
# This file was generated using wireguard-ui (https://github.com/ngoduykhanh/wireguard-ui) # This file was generated using wireguard-ui (https://github.com/ngoduykhanh/wireguard-ui)
# Please don't modify it manually, otherwise your change might got 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 }}
# Private Key updated at: {{ .serverConfig.KeyPair.UpdatedAt }} # Private Key updated at: {{ .serverConfig.KeyPair.UpdatedAt }}
@ -7,7 +7,7 @@
Address = {{$first :=true}}{{range .serverConfig.Interface.Addresses }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}} Address = {{$first :=true}}{{range .serverConfig.Interface.Addresses }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
ListenPort = {{ .serverConfig.Interface.ListenPort }} ListenPort = {{ .serverConfig.Interface.ListenPort }}
PrivateKey = {{ .serverConfig.KeyPair.PrivateKey }} PrivateKey = {{ .serverConfig.KeyPair.PrivateKey }}
MTU = {{ .globalSettings.MTU }} {{if .globalSettings.MTU}}MTU = {{ .globalSettings.MTU }}{{end}}
PostUp = {{ .serverConfig.Interface.PostUp }} PostUp = {{ .serverConfig.Interface.PostUp }}
PostDown = {{ .serverConfig.Interface.PostDown }} PostDown = {{ .serverConfig.Interface.PostDown }}

View file

@ -41,12 +41,15 @@ func BuildClientConfig(client model.Client, server model.Server, setting model.G
if n, err := strconv.Atoi(split[1]); err == nil { if n, err := strconv.Atoi(split[1]); err == nil {
desiredPort = n desiredPort = n
} else { } else {
log.Error("Endpoint appears to be incorrectly formated: ", err) log.Error("Endpoint appears to be incorrectly formatted: ", err)
} }
} }
peerEndpoint := fmt.Sprintf("Endpoint = %s:%d", desiredHost, desiredPort) peerEndpoint := fmt.Sprintf("Endpoint = %s:%d", desiredHost, desiredPort)
peerPersistentKeepalive := fmt.Sprintf("PersistentKeepalive = %d", setting.PersistentKeepalive) peerPersistentKeepalive := ""
if setting.PersistentKeepalive > 0 {
peerPersistentKeepalive = fmt.Sprintf("PersistentKeepalive = %d", setting.PersistentKeepalive)
}
// build the config as string // build the config as string
strConfig := "[Interface]\n" + strConfig := "[Interface]\n" +
@ -380,7 +383,7 @@ func LookupEnvOrBool(key string, defaultVal bool) bool {
if val, ok := os.LookupEnv(key); ok { if val, ok := os.LookupEnv(key); ok {
v, err := strconv.ParseBool(val) v, err := strconv.ParseBool(val)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "LookupEnvOrInt[%s]: %v\n", key, err) fmt.Fprintf(os.Stderr, "LookupEnvOrBool[%s]: %v\n", key, err)
} }
return v return v
} }