Add Apply Config button to save wireguard config file
This commit is contained in:
		
							parent
							
								
									ea36311475
								
							
						
					
					
						commit
						7c3cac8084
					
				|  | @ -389,3 +389,66 @@ func SuggestIPAllocation() echo.HandlerFunc { | ||||||
| 		return c.JSON(http.StatusOK, suggestedIPs) | 		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"}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								main.go
								
								
								
								
							
							
						
						
									
										1
									
								
								main.go
								
								
								
								
							|  | @ -19,5 +19,6 @@ func main() { | ||||||
| 	app.POST("/global-settings", handler.GlobalSettingSubmit()) | 	app.POST("/global-settings", handler.GlobalSettingSubmit()) | ||||||
| 	app.GET("/api/machine-ips", handler.MachineIPAddresses()) | 	app.GET("/api/machine-ips", handler.MachineIPAddresses()) | ||||||
| 	app.GET("/api/suggest-client-ips", handler.SuggestIPAllocation()) | 	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")) | 	app.Logger.Fatal(app.Start("127.0.0.1:5000")) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -10,5 +10,6 @@ type GlobalSetting struct { | ||||||
| 	DNSServers          []string  `json:"dns_servers"` | 	DNSServers          []string  `json:"dns_servers"` | ||||||
| 	MTU                 int       `json:"mtu,string"` | 	MTU                 int       `json:"mtu,string"` | ||||||
| 	PersistentKeepalive int       `json:"persistent_keepalive,string"` | 	PersistentKeepalive int       `json:"persistent_keepalive,string"` | ||||||
|  | 	ConfigFilePath      string    `json:"config_file_path"` | ||||||
| 	UpdatedAt           time.Time `json:"updated_at"` | 	UpdatedAt           time.Time `json:"updated_at"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -58,9 +58,12 @@ | ||||||
| 
 | 
 | ||||||
|         <!-- Right navbar links --> |         <!-- Right navbar links --> | ||||||
|         <div class="navbar-nav ml-auto"> |         <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 |                 data-target="#modal_new_client"><i class="nav-icon fas fa-plus"></i> New | ||||||
|                 Client</button> |                 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> | ||||||
|         </nav> |         </nav> | ||||||
|         <!-- /.navbar --> |         <!-- /.navbar --> | ||||||
|  | @ -169,6 +172,29 @@ | ||||||
|         </div> |         </div> | ||||||
|         <!-- /.modal --> |         <!-- /.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">×</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 --> |         <!-- Content Wrapper. Contains page content --> | ||||||
|         <div class="content-wrapper"> |         <div class="content-wrapper"> | ||||||
|             <!-- Content Header (Page header) --> |             <!-- Content Header (Page header) --> | ||||||
|  | @ -352,6 +378,27 @@ | ||||||
|                 updateIPAllocationSuggestion(); |                 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> |     </script> | ||||||
| 
 | 
 | ||||||
|     <!-- START: On page script --> |     <!-- START: On page script --> | ||||||
|  |  | ||||||
|  | @ -55,6 +55,12 @@ Global Settings | ||||||
|                                     name="persistent_keepalive" placeholder="Persistent Keepalive" |                                     name="persistent_keepalive" placeholder="Persistent Keepalive" | ||||||
|                                     value="{{ .globalSettings.PersistentKeepalive }}"> |                                     value="{{ .globalSettings.PersistentKeepalive }}"> | ||||||
|                             </div> |                             </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> |                         </div> | ||||||
|                         <!-- /.card-body --> |                         <!-- /.card-body --> | ||||||
| 
 | 
 | ||||||
|  | @ -104,7 +110,8 @@ Global Settings | ||||||
|             var dns_servers = $("#dns_servers").val().split(","); |             var dns_servers = $("#dns_servers").val().split(","); | ||||||
|             var mtu = $("#mtu").val(); |             var mtu = $("#mtu").val(); | ||||||
|             var persistent_keepalive = $("#persistent_keepalive").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({ |             $.ajax({ | ||||||
|                 cache: false, |                 cache: false, | ||||||
|  | @ -173,6 +180,9 @@ Global Settings | ||||||
|                     persistent_keepalive: { |                     persistent_keepalive: { | ||||||
|                         required: true, |                         required: true, | ||||||
|                         digits: true |                         digits: true | ||||||
|  |                     }, | ||||||
|  |                     config_file_path: { | ||||||
|  |                         required: true | ||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|                 messages: { |                 messages: { | ||||||
|  | @ -184,6 +194,9 @@ Global Settings | ||||||
|                     persistent_keepalive: { |                     persistent_keepalive: { | ||||||
|                         required: "Please enter a Persistent Keepalive value", |                         required: "Please enter a Persistent Keepalive value", | ||||||
|                         digits: "Persistent keepalive must be an integer" |                         digits: "Persistent keepalive must be an integer" | ||||||
|  |                     }, | ||||||
|  |                     config_file_path: { | ||||||
|  |                         required: "Please enter WireGuard config file path" | ||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|                 errorElement: 'span', |                 errorElement: 'span', | ||||||
|  |  | ||||||
|  | @ -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}} | ||||||
							
								
								
									
										29
									
								
								util/util.go
								
								
								
								
							
							
						
						
									
										29
									
								
								util/util.go
								
								
								
								
							|  | @ -5,7 +5,9 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
|  | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"text/template" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	externalip "github.com/glendc/go-external-ip" | 	externalip "github.com/glendc/go-external-ip" | ||||||
|  | @ -308,3 +310,30 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip | ||||||
| 
 | 
 | ||||||
| 	return true, nil | 	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 | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue