diff --git a/handler/routes.go b/handler/routes.go index 156e701..9c18fc4 100644 --- a/handler/routes.go +++ b/handler/routes.go @@ -160,6 +160,12 @@ func NewClient(db store.IStore) echo.HandlerFunc { return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Allowed IPs must be in CIDR format"}) } + // validate extra AllowedIPs + if util.ValidateExtraAllowedIPs(client.ExtraAllowedIPs) == false { + log.Warnf("Invalid Extra AllowedIPs input from user: %v", client.ExtraAllowedIPs) + return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Extra AllowedIPs must be in CIDR format"}) + } + // gen ID guid := xid.New() client.ID = guid.String() @@ -274,6 +280,11 @@ func UpdateClient(db store.IStore) echo.HandlerFunc { return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Allowed IPs must be in CIDR format"}) } + if util.ValidateExtraAllowedIPs(_client.ExtraAllowedIPs) == false { + log.Warnf("Invalid Allowed IPs input from user: %v", _client.ExtraAllowedIPs) + return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Extra Allowed IPs must be in CIDR format"}) + } + // map new data client.Name = _client.Name client.Email = _client.Email @@ -281,6 +292,7 @@ func UpdateClient(db store.IStore) echo.HandlerFunc { client.UseServerDNS = _client.UseServerDNS client.AllocatedIPs = _client.AllocatedIPs client.AllowedIPs = _client.AllowedIPs + client.ExtraAllowedIPs = _client.ExtraAllowedIPs client.UpdatedAt = time.Now().UTC() // write to the database @@ -628,7 +640,7 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc { fmt.Sprintf("Cannot suggest ip allocation: failed to get available ip from network %s", cidr), }) } - if (strings.Contains(ip, ":")) { + if strings.Contains(ip, ":") { suggestedIPs = append(suggestedIPs, fmt.Sprintf("%s/128", ip)) } else { suggestedIPs = append(suggestedIPs, fmt.Sprintf("%s/32", ip)) diff --git a/model/client.go b/model/client.go index 8e6ba52..c1c7487 100644 --- a/model/client.go +++ b/model/client.go @@ -6,18 +6,19 @@ import ( // Client model type Client struct { - ID string `json:"id"` - PrivateKey string `json:"private_key"` - PublicKey string `json:"public_key"` - PresharedKey string `json:"preshared_key"` - Name string `json:"name"` - Email string `json:"email"` - AllocatedIPs []string `json:"allocated_ips"` - AllowedIPs []string `json:"allowed_ips"` - UseServerDNS bool `json:"use_server_dns"` - Enabled bool `json:"enabled"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ID string `json:"id"` + PrivateKey string `json:"private_key"` + PublicKey string `json:"public_key"` + PresharedKey string `json:"preshared_key"` + Name string `json:"name"` + Email string `json:"email"` + AllocatedIPs []string `json:"allocated_ips"` + AllowedIPs []string `json:"allowed_ips"` + ExtraAllowedIPs []string `json:"extra_allowed_ips"` + UseServerDNS bool `json:"use_server_dns"` + Enabled bool `json:"enabled"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } // ClientData includes the Client and extra data diff --git a/templates/base.html b/templates/base.html index 6705c6d..b3c254c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -163,6 +163,11 @@ +
+ + +
@@ -293,6 +298,12 @@ const allocated_ips = $("#client_allocated_ips").val().split(","); const allowed_ips = $("#client_allowed_ips").val().split(","); let use_server_dns = false; + let extra_allowed_ips = []; + + if ($("#client_extra_allowed_ips").val() !== "") { + extra_allowed_ips = $("#client_extra_allowed_ips").val().split(","); + } + if ($("#use_server_dns").is(':checked')){ use_server_dns = true; @@ -305,7 +316,7 @@ } const data = {"name": name, "email": email, "allocated_ips": allocated_ips, "allowed_ips": allowed_ips, - "use_server_dns": use_server_dns, "enabled": enabled}; + "extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled}; $.ajax({ cache: false, @@ -376,6 +387,16 @@ 'placeholderColor': '#666666' }); + $("#client_extra_allowed_ips").tagsInput({ + 'width': '100%', + 'height': '75%', + 'interactive': true, + 'defaultText': 'Add More', + 'removeWithBackspace': true, + 'minChars': 0, + 'placeholderColor': '#666666' + }); + // New client form validation $(document).ready(function () { $.validator.setDefaults({ @@ -414,6 +435,7 @@ $("#client_name").val(""); $("#client_email").val(""); $("#client_allocated_ips").importTags(''); + $("#client_extra_allowed_ips").importTags(''); updateIPAllocationSuggestion(); }); }); diff --git a/templates/clients.html b/templates/clients.html index 2426fb7..3f39a2a 100644 --- a/templates/clients.html +++ b/templates/clients.html @@ -86,6 +86,11 @@ Wireguard Clients
+
+ + +
@@ -302,6 +307,16 @@ Wireguard Clients 'placeholderColor': '#666666' }); + modal.find("#_client_extra_allowed_ips").tagsInput({ + 'width': '100%', + 'height': '75%', + 'interactive': true, + 'defaultText': 'Add More', + 'removeWithBackspace' : true, + 'minChars': 0, + 'placeholderColor': '#666666' + }) + // update client modal data $.ajax({ cache: false, @@ -327,6 +342,11 @@ Wireguard Clients modal.find("#_client_allowed_ips").addTag(obj); }); + modal.find("#_client_extra_allowed_ips").importTags(''); + client.extra_allowed_ips.forEach(function (obj) { + modal.find("#_client_extra_allowed_ips").addTag(obj); + }); + modal.find("#_use_server_dns").prop("checked", client.use_server_dns); modal.find("#_enabled").prop("checked", client.enabled); }, @@ -371,6 +391,11 @@ Wireguard Clients const allocated_ips = $("#_client_allocated_ips").val().split(","); const allowed_ips = $("#_client_allowed_ips").val().split(","); let use_server_dns = false; + let extra_allowed_ips = []; + + if( $("#_client_extra_allowed_ips").val() !== "" ) { + extra_allowed_ips = $("#_client_extra_allowed_ips").val().split(","); + } if ($("#_use_server_dns").is(':checked')){ use_server_dns = true; @@ -383,7 +408,7 @@ Wireguard Clients } const data = {"id": client_id, "name": name, "email": email, "allocated_ips": allocated_ips, - "allowed_ips": allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled}; + "allowed_ips": allowed_ips, "extra_allowed_ips": extra_allowed_ips, "use_server_dns": use_server_dns, "enabled": enabled}; $.ajax({ cache: false, diff --git a/templates/wg.conf b/templates/wg.conf index c3cc7c9..5ac207b 100644 --- a/templates/wg.conf +++ b/templates/wg.conf @@ -20,5 +20,5 @@ PostDown = {{ .serverConfig.Interface.PostDown }} [Peer] PublicKey = {{ .Client.PublicKey }} PresharedKey = {{ .Client.PresharedKey }} -AllowedIPs = {{$first :=true}}{{range .Client.AllocatedIPs }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}} +AllowedIPs = {{$first :=true}}{{range .Client.AllocatedIPs }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}{{range .Client.ExtraAllowedIPs }},{{.}}{{end}} {{end}}{{end}} diff --git a/util/util.go b/util/util.go index 2269537..7622918 100644 --- a/util/util.go +++ b/util/util.go @@ -76,10 +76,18 @@ func ValidateCIDR(cidr string) bool { } // ValidateCIDRList to validate a list of network CIDR -func ValidateCIDRList(cidrs []string) bool { +func ValidateCIDRList(cidrs []string, allowEmpty bool) bool { for _, cidr := range cidrs { - if ValidateCIDR(cidr) == false { - return false + if allowEmpty { + if len(cidr) > 0 { + if ValidateCIDR(cidr) == false { + return false + } + } + } else { + if ValidateCIDR(cidr) == false { + return false + } } } return true @@ -87,7 +95,15 @@ func ValidateCIDRList(cidrs []string) bool { // ValidateAllowedIPs to validate allowed ip addresses in CIDR format func ValidateAllowedIPs(cidrs []string) bool { - if ValidateCIDRList(cidrs) == false { + if ValidateCIDRList(cidrs, false) == false { + return false + } + return true +} + +// ValidateExtraAllowedIPs to validate extra Allowed ip addresses, allowing empty strings +func ValidateExtraAllowedIPs(cidrs []string) bool { + if ValidateCIDRList(cidrs, true) == false { return false } return true @@ -95,7 +111,7 @@ func ValidateAllowedIPs(cidrs []string) bool { // ValidateServerAddresses to validate allowed ip addresses in CIDR format func ValidateServerAddresses(cidrs []string) bool { - if ValidateCIDRList(cidrs) == false { + if ValidateCIDRList(cidrs, false) == false { return false } return true