Add Apply Config button to save wireguard config file

This commit is contained in:
Khanh Ngo 2020-04-23 09:29:44 +07:00
parent ea36311475
commit 7c3cac8084
No known key found for this signature in database
GPG Key ID: D5FAA6A16150E49E
7 changed files with 177 additions and 2 deletions

View File

@ -389,3 +389,66 @@ func SuggestIPAllocation() echo.HandlerFunc {
return c.JSON(http.StatusOK, suggestedIPs)
}
}
// ApplyServerConfig handler to write config file and restart Wireguard server
func ApplyServerConfig() echo.HandlerFunc {
return func(c echo.Context) error {
// initialize database directory
dir := "./db"
db, err := scribble.New(dir, nil)
if err != nil {
log.Error("Cannot initialize the database: ", err)
}
// read server information
serverInterface := model.ServerInterface{}
if err := db.Read("server", "interfaces", &serverInterface); err != nil {
log.Error("Cannot fetch server interface config from database: ", err)
}
serverKeyPair := model.ServerKeypair{}
if err := db.Read("server", "keypair", &serverKeyPair); err != nil {
log.Error("Cannot fetch server key pair from database: ", err)
}
server := model.Server{}
server.Interface = &serverInterface
server.KeyPair = &serverKeyPair
// read global settings
globalSettings := model.GlobalSetting{}
if err := db.Read("server", "global_settings", &globalSettings); err != nil {
log.Error("Cannot fetch global settings from database: ", err)
}
// read client information and build a client list
records, err := db.ReadAll("clients")
if err != nil {
log.Error("Cannot fetch clients from database: ", err)
}
clientDataList := []model.ClientData{}
for _, f := range records {
client := model.Client{}
clientData := model.ClientData{}
// get client info
if err := json.Unmarshal([]byte(f), &client); err != nil {
log.Error("Cannot decode client json structure: ", err)
}
clientData.Client = &client
// create the list of clients and their qrcode data
clientDataList = append(clientDataList, clientData)
}
// Write config file
err = util.WriteWireGuardServerConfig(server, clientDataList, globalSettings)
if err != nil {
log.Error("Cannot apply server config: ", err)
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, fmt.Sprintf("Cannot apply server config: %v", err)})
}
return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Applied server config successfully"})
}
}

View File

@ -19,5 +19,6 @@ func main() {
app.POST("/global-settings", handler.GlobalSettingSubmit())
app.GET("/api/machine-ips", handler.MachineIPAddresses())
app.GET("/api/suggest-client-ips", handler.SuggestIPAllocation())
app.GET("/api/apply-wg-config", handler.ApplyServerConfig())
app.Logger.Fatal(app.Start("127.0.0.1:5000"))
}

View File

@ -10,5 +10,6 @@ type GlobalSetting struct {
DNSServers []string `json:"dns_servers"`
MTU int `json:"mtu,string"`
PersistentKeepalive int `json:"persistent_keepalive,string"`
ConfigFilePath string `json:"config_file_path"`
UpdatedAt time.Time `json:"updated_at"`
}

View File

@ -58,9 +58,12 @@
<!-- Right navbar links -->
<div class="navbar-nav ml-auto">
<button type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
<button style="margin-left: 0.5em;" type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
data-target="#modal_new_client"><i class="nav-icon fas fa-plus"></i> New
Client</button>
<button style="margin-left: 0.5em;" type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal"
data-target="#modal_apply_config"><i class="nav-icon fas fa-check"></i> Apply
Config</button>
</nav>
</nav>
<!-- /.navbar -->
@ -169,6 +172,29 @@
</div>
<!-- /.modal -->
<div class="modal fade" id="modal_apply_config">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Apply Config</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>Do you want to write config file and restart WireGuard server?</p>
</div>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger" id="apply_config_confirm">Apply</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
@ -352,6 +378,27 @@
updateIPAllocationSuggestion();
});
});
// apply_config_confirm button event
$(document).ready(function () {
$('#apply_config_confirm').click(function () {
$.ajax({
cache: false,
method: 'GET',
url: '/api/apply-wg-config',
dataType: 'json',
contentType: "application/json",
success: function(data) {
$('#modal_apply_config').modal('hide');
toastr.success('Applied config successfully');
},
error: function(jqXHR, exception) {
var responseJson = jQuery.parseJSON(jqXHR.responseText);
toastr.error(responseJson['message']);
}
});
});
});
</script>
<!-- START: On page script -->

View File

@ -55,6 +55,12 @@ Global Settings
name="persistent_keepalive" placeholder="Persistent Keepalive"
value="{{ .globalSettings.PersistentKeepalive }}">
</div>
<div class="form-group">
<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 }}">
</div>
</div>
<!-- /.card-body -->
@ -104,7 +110,8 @@ Global Settings
var dns_servers = $("#dns_servers").val().split(",");
var mtu = $("#mtu").val();
var persistent_keepalive = $("#persistent_keepalive").val();
var data = {"endpoint_address": endpoint_address, "dns_servers": dns_servers, "mtu": mtu, "persistent_keepalive": persistent_keepalive};
var config_file_path = $("#config_file_path").val();
var data = {"endpoint_address": endpoint_address, "dns_servers": dns_servers, "mtu": mtu, "persistent_keepalive": persistent_keepalive, "config_file_path": config_file_path};
$.ajax({
cache: false,
@ -173,6 +180,9 @@ Global Settings
persistent_keepalive: {
required: true,
digits: true
},
config_file_path: {
required: true
}
},
messages: {
@ -184,6 +194,9 @@ Global Settings
persistent_keepalive: {
required: "Please enter a Persistent Keepalive value",
digits: "Persistent keepalive must be an integer"
},
config_file_path: {
required: "Please enter WireGuard config file path"
}
},
errorElement: 'span',

21
templates/wg.conf Normal file
View File

@ -0,0 +1,21 @@
# 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.
# Address updated at: {{ .serverConfig.Interface.UpdatedAt }}
# Private Key updated at: {{ .serverConfig.KeyPair.UpdatedAt }}
[Interface]
Address = {{$first :=true}}{{range .serverConfig.Interface.Addresses }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
ListenPort = {{ .serverConfig.Interface.ListenPort }}
PrivateKey = {{ .serverConfig.KeyPair.PrivateKey }}
MTU = {{ .globalSettings.MTU }}
{{range .clientDataList}}
# ID: {{ .Client.ID }}
# Name: {{ .Client.Name }}
# Email: {{ .Client.Email }}
# Created at: {{ .Client.CreatedAt }}
# Update at: {{ .Client.UpdatedAt }}
[Peer]
PublicKey = {{ .Client.PublicKey }}
AllowedIPs = {{$first :=true}}{{range .Client.AllocatedIPs }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
{{end}}

View File

@ -5,7 +5,9 @@ import (
"errors"
"fmt"
"net"
"os"
"strings"
"text/template"
"time"
externalip "github.com/glendc/go-external-ip"
@ -308,3 +310,30 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip
return true, nil
}
// WriteWireGuardServerConfig to write Wireguard server config. e.g. wg0.conf
func WriteWireGuardServerConfig(serverConfig model.Server, clientDataList []model.ClientData, globalSettings model.GlobalSetting) error {
t, err := template.ParseFiles("templates/wg.conf")
if err != nil {
return err
}
f, err := os.Create(globalSettings.ConfigFilePath)
if err != nil {
return err
}
config := map[string]interface{}{
"serverConfig": serverConfig,
"clientDataList": clientDataList,
"globalSettings": globalSettings,
}
err = t.Execute(f, config)
if err != nil {
return err
}
f.Close()
return nil
}