diff --git a/Dockerfile b/Dockerfile
index c4e3b6a98e31238f9eab6256e5dc96958e25c703..ef1f911faef46c619123cb2e003d1c97d2a23b91 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,7 +3,7 @@ WORKDIR /app
 ADD . .
 RUN go build -o wg-gen-web-linux
 
-FROM node:10-alpine as build-front
+FROM node:10-alpine AS build-front
 WORKDIR /app
 ADD ui .
 RUN npm install
diff --git a/core/client.go b/core/client.go
index 8d49c703c0fc5c465fc3641931d8fb97f2bff07c..e2839fcd5ead7318185e2a349681cff44d00acdd 100644
--- a/core/client.go
+++ b/core/client.go
@@ -22,6 +22,17 @@ import (
 
 // CreateClient client with all necessary data
 func CreateClient(client *model.Client) (*model.Client, error) {
+	// check if client is valid
+	errs := client.IsValid()
+	if len(errs) != 0 {
+		for _, err := range errs {
+			log.WithFields(log.Fields{
+				"err": err,
+			}).Error("client validation error")
+		}
+		return nil, errors.New("failed to validate client")
+	}
+
 	u := uuid.NewV4()
 	client.Id = u.String()
 
@@ -32,32 +43,14 @@ func CreateClient(client *model.Client) (*model.Client, error) {
 	client.PrivateKey = key.String()
 	client.PublicKey = key.PublicKey().String()
 
-	// find available IP address from selected networks
-	clients, err := ReadClients()
+	reserverIps, err := GetAllReservedIps()
 	if err != nil {
 		return nil, err
 	}
 
-	reserverIps := make([]string, 0)
-	for _, client := range clients {
-		ips := strings.Split(client.Address, ",")
-		for i := range ips {
-			if util.IsIPv6(ips[i]) {
-				ips[i] = strings.ReplaceAll(strings.TrimSpace(ips[i]), "/128", "")
-			} else {
-				ips[i] = strings.ReplaceAll(strings.TrimSpace(ips[i]), "/32", "")
-			}
-		}
-		reserverIps = append(reserverIps, ips...)
-	}
-
-	networks := strings.Split(client.Address, ",")
-	for i := range networks {
-		networks[i] = strings.TrimSpace(networks[i])
-	}
 	ips := make([]string, 0)
-	for _, network := range networks {
-		ip, err := util.GetAvailableIp(network, reserverIps)
+	for _, network := range strings.Split(client.Address, ",") {
+		ip, err := util.GetAvailableIp(strings.TrimSpace(network), reserverIps)
 		if err != nil {
 			return nil, err
 		}
@@ -109,6 +102,18 @@ func UpdateClient(Id string, client *model.Client) (*model.Client, error) {
 	if current.Id != client.Id {
 		return nil, errors.New("records Id mismatch")
 	}
+
+	// check if client is valid
+	errs := client.IsValid()
+	if len(errs) != 0 {
+		for _, err := range errs {
+			log.WithFields(log.Fields{
+				"err": err,
+			}).Error("client validation error")
+		}
+		return nil, errors.New("failed to validate client")
+	}
+
 	// keep keys
 	client.PrivateKey = current.PrivateKey
 	client.PublicKey = current.PublicKey
@@ -159,7 +164,7 @@ func ReadClients() ([]*model.Client, error) {
 				log.WithFields(log.Fields{
 					"err":  err,
 					"path": f.Name(),
-				}).Error("failed to storage.Destorage.Serialize client")
+				}).Error("failed to deserialize client")
 			} else {
 				clients = append(clients, c.(*model.Client))
 			}
diff --git a/core/server.go b/core/server.go
index 5069498cc34a3d27f6d9e7ea609c9356ad6c48dc..a4535d794927d85d2e76dab6089e45bc2cca0690 100644
--- a/core/server.go
+++ b/core/server.go
@@ -1,6 +1,8 @@
 package core
 
 import (
+	"errors"
+	log "github.com/sirupsen/logrus"
 	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/model"
 	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/storage"
 	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/template"
@@ -8,6 +10,7 @@ import (
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"os"
 	"path/filepath"
+	"strings"
 	"time"
 )
 
@@ -62,6 +65,18 @@ func UpdateServer(server *model.Server) (*model.Server, error) {
 	if err != nil {
 		return nil, err
 	}
+
+	// check if server is valid
+	errs := server.IsValid()
+	if len(errs) != 0 {
+		for _, err := range errs {
+			log.WithFields(log.Fields{
+				"err": err,
+			}).Error("server validation error")
+		}
+		return nil, errors.New("failed to validate server")
+	}
+
 	server.PrivateKey = current.(*model.Server).PrivateKey
 	server.PublicKey = current.(*model.Server).PublicKey
 	server.PresharedKey = current.(*model.Server).PresharedKey
@@ -100,3 +115,46 @@ func UpdateServerConfigWg() error {
 
 	return nil
 }
+
+// GetAllReservedIps the list of all reserved IPs, client and server
+func GetAllReservedIps() ([]string, error) {
+	clients, err := ReadClients()
+	if err != nil {
+		return nil, err
+	}
+
+	server, err := ReadServer()
+	if err != nil {
+		return nil, err
+	}
+
+	reserverIps := make([]string, 0)
+
+	for _, client := range clients {
+		for _, cidr := range strings.Split(client.Address, ",") {
+			ip, err := util.GetIpFromCidr(strings.TrimSpace(cidr))
+			if err != nil {
+				log.WithFields(log.Fields{
+					"err":  err,
+					"cidr": err,
+				}).Error("failed to ip from cidr")
+			} else {
+				reserverIps = append(reserverIps, ip)
+			}
+		}
+	}
+
+	for _, cidr := range strings.Split(server.Address, ",") {
+		ip, err := util.GetIpFromCidr(strings.TrimSpace(cidr))
+		if err != nil {
+			log.WithFields(log.Fields{
+				"err":  err,
+				"cidr": err,
+			}).Error("failed to ip from cidr")
+		} else {
+			reserverIps = append(reserverIps, ip)
+		}
+	}
+
+	return reserverIps, nil
+}
diff --git a/model/client.go b/model/client.go
index 7b182c32ff1f1e4daa8113cd5c02e458b347208b..3ff5dcba2e0f83020c0bea28fa804592ae60041c 100644
--- a/model/client.go
+++ b/model/client.go
@@ -1,6 +1,11 @@
 package model
 
-import "time"
+import (
+	"fmt"
+	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/util"
+	"strings"
+	"time"
+)
 
 // Client structure
 type Client struct {
@@ -8,10 +13,53 @@ type Client struct {
 	Name       string    `json:"name"`
 	Email      string    `json:"email"`
 	Enable     bool      `json:"enable"`
-	Created    time.Time `json:"created"`
-	Updated    time.Time `json:"updated"`
 	AllowedIPs string    `json:"allowedIPs"`
 	Address    string    `json:"address"`
 	PrivateKey string    `json:"privateKey"`
 	PublicKey  string    `json:"publicKey"`
+	Created    time.Time `json:"created"`
+	Updated    time.Time `json:"updated"`
+}
+
+func (a Client) IsValid() []error {
+	errs := make([]error, 0)
+
+	// check if the name empty
+	if a.Name == "" {
+		errs = append(errs, fmt.Errorf("name is required"))
+	}
+	// check the name field is between 3 to 40 chars
+	if len(a.Name) < 2 || len(a.Name) > 40 {
+		errs = append(errs, fmt.Errorf("name field must be between 2-40 chars"))
+	}
+	// check if the email empty
+	if a.Email == "" {
+		errs = append(errs, fmt.Errorf("email field is required"))
+	}
+	// check if email valid
+	if !util.RegexpEmail.MatchString(a.Email) {
+		errs = append(errs, fmt.Errorf("email %s is invalid", a.Email))
+	}
+	// check if the allowedIPs empty
+	if a.AllowedIPs == "" {
+		errs = append(errs, fmt.Errorf("allowedIPs field is required"))
+	}
+	// check if the allowedIPs are valid
+	for _, allowedIP := range strings.Split(a.AllowedIPs, ",") {
+		if !util.IsValidCidr(strings.TrimSpace(allowedIP)) {
+			errs = append(errs, fmt.Errorf("allowedIP %s is invalid", allowedIP))
+		}
+	}
+	// check if the address empty
+	if a.Address == "" {
+		errs = append(errs, fmt.Errorf("address field is required"))
+	}
+	// check if the address are valid
+	for _, address := range strings.Split(a.Address, ",") {
+		if !util.IsValidCidr(strings.TrimSpace(address)) {
+			errs = append(errs, fmt.Errorf("address %s is invalid", address))
+		}
+	}
+
+	return errs
 }
diff --git a/model/server.go b/model/server.go
index e27df514ab1633a13157b52598480224f1ffc4bc..cb52ce02116d6289c441274152345fe93caf3ac7 100644
--- a/model/server.go
+++ b/model/server.go
@@ -1,12 +1,15 @@
 package model
 
-import "time"
+import (
+	"fmt"
+	"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/util"
+	"strings"
+	"time"
+)
 
 // Server structure
 type Server struct {
 	Name                string    `json:"name"`
-	Created             time.Time `json:"created"`
-	Updated             time.Time `json:"updated"`
 	Address             string    `json:"address"`
 	ListenPort          int       `json:"listenPort"`
 	PrivateKey          string    `json:"privateKey"`
@@ -19,4 +22,53 @@ type Server struct {
 	PostUp              string    `json:"postUp"`
 	PreDown             string    `json:"preDown"`
 	PostDown            string    `json:"postDown"`
+	Created             time.Time `json:"created"`
+	Updated             time.Time `json:"updated"`
+}
+
+func (a Server) IsValid() []error {
+	errs := make([]error, 0)
+
+	// check if the name empty
+	if a.Name == "" {
+		errs = append(errs, fmt.Errorf("name is required"))
+	}
+	// check the name field is between 3 to 40 chars
+	if len(a.Name) < 2 || len(a.Name) > 40 {
+		errs = append(errs, fmt.Errorf("name must be between 2-40 chars"))
+	}
+	// check if the address empty
+	if a.Address == "" {
+		errs = append(errs, fmt.Errorf("address is required"))
+	}
+	// check if the address are valid
+	for _, address := range strings.Split(a.Address, ",") {
+		if !util.IsValidCidr(strings.TrimSpace(address)) {
+			errs = append(errs, fmt.Errorf("address %s is invalid", address))
+		}
+	}
+	// check if the listenPort is valid
+	if a.ListenPort < 0 || a.ListenPort > 65535 {
+		errs = append(errs, fmt.Errorf("listenPort %s is invalid", a.ListenPort))
+	}
+	// check if the endpoint empty
+	if a.Endpoint == "" {
+		errs = append(errs, fmt.Errorf("endpoint is required"))
+	}
+	// check if the persistentKeepalive is valid
+	if a.PersistentKeepalive < 0 {
+		errs = append(errs, fmt.Errorf("persistentKeepalive %d is invalid", a.PersistentKeepalive))
+	}
+	// check if the dns empty
+	if a.Dns == "" {
+		errs = append(errs, fmt.Errorf("dns is required"))
+	}
+	// check if the address are valid
+	for _, dns := range strings.Split(a.Dns, ",") {
+		if !util.IsValidIp(strings.TrimSpace(dns)) {
+			errs = append(errs, fmt.Errorf("dns %s is invalid", dns))
+		}
+	}
+
+	return errs
 }
diff --git a/ui/src/App.vue b/ui/src/App.vue
index 753e268f9cad1bb20fcd7621653f77e762635298..e36928987b7c31b592ee07aeb10e309af1d7abdf 100644
--- a/ui/src/App.vue
+++ b/ui/src/App.vue
@@ -13,7 +13,7 @@
     </v-content>
 
     <v-footer app>
-      <span>Copyright <a class="pr-1 pl-1" href="http://www.wtfpl.net/" target="_blank">WTFPL</a> &copy; {{ new Date().getFullYear() }} Created with</span><v-icon class="pr-1 pl-1">mdi-heart</v-icon><span>by</span><a class="pr-1 pl-1" href="mailto:vx3r@127-0-0-1.fr">vx3r</a>
+      <span>License <a class="pr-1 pl-1" href="http://www.wtfpl.net/" target="_blank">WTFPL</a> &copy; {{ new Date().getFullYear() }} Created with</span><v-icon class="pr-1 pl-1">mdi-heart</v-icon><span>by</span><a class="pr-1 pl-1" href="mailto:vx3r@127-0-0-1.fr">vx3r</a>
     </v-footer>
 
   </v-app>
diff --git a/ui/src/views/Home.vue b/ui/src/views/Home.vue
index 1968b0d55afee8a99feb157cdc94cac417f66697..7a6d2db3c8e4c819d054c5d49cb7edcbcde226c5 100644
--- a/ui/src/views/Home.vue
+++ b/ui/src/views/Home.vue
@@ -318,12 +318,14 @@
                   @click="addClient(client)"
           >
             Submit
+            <v-icon right dark>mdi-check-outline</v-icon>
           </v-btn>
           <v-btn
                   color="primary"
                   @click="dialogAddClient = false"
           >
             Cancel
+            <v-icon right dark>mdi-close-circle-outline</v-icon>
           </v-btn>
         </v-card-actions>
       </v-card>
@@ -361,6 +363,26 @@
                         ]"
                         required
                 />
+                <v-combobox
+                        v-model="client.address"
+                        chips
+                        hint="Write IPv4 or IPv6 CIDR and hit enter"
+                        label="Addresses"
+                        multiple
+                        dark
+                >
+                  <template v-slot:selection="{ attrs, item, select, selected }">
+                    <v-chip
+                            v-bind="attrs"
+                            :input-value="selected"
+                            close
+                            @click="select"
+                            @click:close="client.address.splice(client.address.indexOf(item), 1)"
+                    >
+                      <strong>{{ item }}</strong>&nbsp;
+                    </v-chip>
+                  </template>
+                </v-combobox>
                 <v-combobox
                         v-model="client.allowedIPs"
                         chips
@@ -393,12 +415,14 @@
                   @click="updateClient(client)"
           >
             Submit
+            <v-icon right dark>mdi-check-outline</v-icon>
           </v-btn>
           <v-btn
                   color="primary"
                   @click="dialogEditClient = false"
           >
             Cancel
+            <v-icon right dark>mdi-close-circle-outline</v-icon>
           </v-btn>
         </v-card-actions>
       </v-card>
@@ -460,13 +484,19 @@
         this.$get(`/client/${id}`).then((res) => {
           this.dialogEditClient = true;
           res.allowedIPs = res.allowedIPs.split(',');
+          res.address = res.address.split(',');
           this.client = res
         }).catch((e) => {
           this.notify('error', e.response.status + ' ' + e.response.statusText);
         });
       },
       disableClient(client) {
-        client.allowedIPs = client.allowedIPs.split(',');
+        if(!Array.isArray(client.allowedIPs)){
+          client.allowedIPs = client.allowedIPs.split(',');
+        }
+        if(!Array.isArray(client.address)){
+          client.address = client.address.split(',');
+        }
         this.updateClient(client)
       },
       getData() {
@@ -476,7 +506,6 @@
           this.server = res;
           this.clientAddress = this.serverAddress = this.server.address
         }).catch((e) => {
-          console.log(e)
           this.notify('error', e.response.status + ' ' + e.response.statusText);
         });
 
@@ -564,6 +593,7 @@
         }
       },
       updateClient(client) {
+        // check allowed IPs
         if (client.allowedIPs.length < 1) {
           this.notify('error', 'Please provide at least one valid CIDR address for client allowed IPs');
           return;
@@ -574,9 +604,21 @@
             return
           }
         }
-
+        // check address
+        if (client.address.length < 1) {
+          this.notify('error', 'Please provide at least one valid CIDR address for client');
+          return;
+        }
+        for (let i = 0; i < client.address.length; i++){
+          if (this.$isCidr(client.address[i]) === 0) {
+            this.notify('error', 'Invalid CIDR detected, please correct before submitting');
+            return
+          }
+        }
+        // all good, submit
         this.dialogEditClient = false;
         client.allowedIPs = client.allowedIPs.join(',');
+        client.address = client.address.join(',');
 
         this.$patch(`/client/${client.id}`, client).then((res) => {
           this.notify('success', "Client successfully updated");
diff --git a/util/util.go b/util/util.go
index cced1a9b01ec72b374b6edff1e68c77d72122a84..403f82e4bb436173aec13b5bb6f39a9e8342ddbd 100644
--- a/util/util.go
+++ b/util/util.go
@@ -5,7 +5,11 @@ import (
 	"io/ioutil"
 	"net"
 	"os"
-	"strings"
+	"regexp"
+)
+
+var (
+	RegexpEmail = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
 )
 
 // ReadFile file content
@@ -86,7 +90,31 @@ func GetAllAddressesFromCidr(cidr string) ([]string, error) {
 
 // IsIPv6 check if given ip is IPv6
 func IsIPv6(address string) bool {
-	return strings.Count(address, ":") >= 2
+	ip := net.ParseIP(address)
+	if ip == nil {
+		return false
+	}
+	return ip.To4() == nil
+}
+
+// IsValidIp check if ip is valid
+func IsValidIp(ip string) bool {
+	return net.ParseIP(ip) != nil
+}
+
+// IsValidCidr check if CIDR is valid
+func IsValidCidr(cidr string) bool {
+	_, _, err := net.ParseCIDR(cidr)
+	return err == nil
+}
+
+// GetIpFromCidr get ip from cidr
+func GetIpFromCidr(cidr string) (string, error) {
+	ip, _, err := net.ParseCIDR(cidr)
+	if err != nil {
+		return "", err
+	}
+	return ip.String(), nil
 }
 
 //  http://play.golang.org/p/m8TNTtygK0