From ba768dd2c3fce4c0edc3d0a056aa6ef7d7421bf8 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Mon, 5 Apr 2021 20:00:11 +0200 Subject: [PATCH] improve client mode, todo: migrate peers (new db schema) --- assets/tpl/admin_edit_client.html | 6 +-- assets/tpl/admin_index.html | 2 +- internal/server/configuration.go | 2 +- internal/server/handlers_interface.go | 1 - internal/server/server_helper.go | 69 +++++++++++---------------- internal/wireguard/peermanager.go | 33 ++++--------- internal/wireguard/tpl/interface.tpl | 7 +-- internal/wireguard/tpl/peer.tpl | 2 +- 8 files changed, 43 insertions(+), 79 deletions(-) diff --git a/assets/tpl/admin_edit_client.html b/assets/tpl/admin_edit_client.html index 1cb0bfd..a33a36b 100644 --- a/assets/tpl/admin_edit_client.html +++ b/assets/tpl/admin_edit_client.html @@ -28,7 +28,6 @@ - {{if .EditableKeys}}
@@ -138,7 +137,6 @@ -
@@ -153,8 +151,8 @@
- - + +
diff --git a/assets/tpl/admin_index.html b/assets/tpl/admin_index.html index 026665a..8077b7f 100644 --- a/assets/tpl/admin_index.html +++ b/assets/tpl/admin_index.html @@ -163,7 +163,7 @@ {{$p.Identifier}} - {{if eq $.Device.Type "server"}}{{$p.PublicKey}}{{end}}{{if eq $.Device.Type "client"}}{{$p.EndpointPublicKey}}{{end}} + {{$p.PublicKey}} {{$p.Email}} {{$p.IPsStr}} {{$p.LastHandshake}} diff --git a/internal/server/configuration.go b/internal/server/configuration.go index 2727967..5f2f3a7 100644 --- a/internal/server/configuration.go +++ b/internal/server/configuration.go @@ -106,7 +106,7 @@ func NewConfig() *Config { cfg.LDAP.DisabledAttribute = "userAccountControl" cfg.LDAP.AdminLdapGroup = "CN=WireGuardAdmins,OU=_O_IT,DC=COMPANY,DC=LOCAL" - cfg.WG.DeviceNames = []string{"wg0"} + cfg.WG.DeviceNames = []string{"wg0", "wg1"} cfg.WG.DefaultDeviceName = "wg0" cfg.WG.ConfigDirectoryPath = "/etc/wireguard" cfg.WG.ManageIPAddresses = true diff --git a/internal/server/handlers_interface.go b/internal/server/handlers_interface.go index 457ac3f..f22dec5 100644 --- a/internal/server/handlers_interface.go +++ b/internal/server/handlers_interface.go @@ -162,7 +162,6 @@ func (s *Server) GetApplyGlobalConfig(c *gin.Context) { peer.PersistentKeepalive = device.DefaultPersistentKeepalive peer.DNSStr = device.DNSStr peer.Mtu = device.Mtu - peer.EndpointPublicKey = device.PublicKey if err := s.peers.UpdatePeer(peer); err != nil { SetFlashMessage(c, err.Error(), "danger") diff --git a/internal/server/server_helper.go b/internal/server/server_helper.go index b0d8863..5eca32d 100644 --- a/internal/server/server_helper.go +++ b/internal/server/server_helper.go @@ -23,37 +23,37 @@ func (s *Server) PrepareNewPeer(device string) (wireguard.Peer, error) { peer := wireguard.Peer{} peer.IsNew = true - peerIPs := make([]string, len(deviceIPs)) - for i := range deviceIPs { - freeIP, err := s.peers.GetAvailableIp(device, deviceIPs[i]) - if err != nil { - return wireguard.Peer{}, errors.WithMessage(err, "failed to get available IP addresses") - } - peerIPs[i] = freeIP - } - peer.SetIPAddresses(peerIPs...) - psk, err := wgtypes.GenerateKey() - if err != nil { - return wireguard.Peer{}, errors.Wrap(err, "failed to generate key") - } - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - return wireguard.Peer{}, errors.Wrap(err, "failed to generate private key") - } - peer.PresharedKey = psk.String() - peer.PrivateKey = key.String() - peer.PublicKey = key.PublicKey().String() - peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey))) switch dev.Type { case wireguard.DeviceTypeServer: - peer.EndpointPublicKey = dev.PublicKey + peerIPs := make([]string, len(deviceIPs)) + for i := range deviceIPs { + freeIP, err := s.peers.GetAvailableIp(device, deviceIPs[i]) + if err != nil { + return wireguard.Peer{}, errors.WithMessage(err, "failed to get available IP addresses") + } + peerIPs[i] = freeIP + } + peer.SetIPAddresses(peerIPs...) + psk, err := wgtypes.GenerateKey() + if err != nil { + return wireguard.Peer{}, errors.Wrap(err, "failed to generate key") + } + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + return wireguard.Peer{}, errors.Wrap(err, "failed to generate private key") + } + peer.PresharedKey = psk.String() + peer.PrivateKey = key.String() + peer.PublicKey = key.PublicKey().String() + peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey))) peer.Endpoint = dev.DefaultEndpoint peer.DNSStr = dev.DNSStr peer.PersistentKeepalive = dev.DefaultPersistentKeepalive peer.AllowedIPsStr = dev.DefaultAllowedIPsStr peer.Mtu = dev.Mtu case wireguard.DeviceTypeClient: + peer.UID = "newendpoint" } return peer, nil @@ -90,7 +90,7 @@ func (s *Server) CreatePeer(device string, peer wireguard.Peer) error { peerIPs := peer.GetIPAddresses() peer.AllowedIPsStr = dev.DefaultAllowedIPsStr - if len(peerIPs) == 0 { + if len(peerIPs) == 0 && dev.Type == wireguard.DeviceTypeServer { peerIPs = make([]string, len(deviceIPs)) for i := range deviceIPs { freeIP, err := s.peers.GetAvailableIp(device, deviceIPs[i]) @@ -101,7 +101,7 @@ func (s *Server) CreatePeer(device string, peer wireguard.Peer) error { } peer.SetIPAddresses(peerIPs...) } - if peer.PrivateKey == "" { // if private key is empty create a new one + if peer.PrivateKey == "" && dev.Type == wireguard.DeviceTypeServer { // if private key is empty create a new one psk, err := wgtypes.GenerateKey() if err != nil { return errors.Wrap(err, "failed to generate key") @@ -141,12 +141,7 @@ func (s *Server) UpdatePeer(peer wireguard.Peer, updateTime time.Time) error { var err error switch { case peer.DeactivatedAt != nil && *peer.DeactivatedAt == updateTime: - switch dev.Type { - case wireguard.DeviceTypeServer: - err = s.wg.RemovePeer(peer.DeviceName, peer.PublicKey) - case wireguard.DeviceTypeClient: - err = s.wg.RemovePeer(peer.DeviceName, peer.EndpointPublicKey) - } + err = s.wg.RemovePeer(peer.DeviceName, peer.PublicKey) case peer.DeactivatedAt == nil && currentPeer.Peer != nil: err = s.wg.UpdatePeer(peer.DeviceName, peer.GetConfig(&dev)) case peer.DeactivatedAt == nil && currentPeer.Peer == nil: @@ -156,6 +151,8 @@ func (s *Server) UpdatePeer(peer wireguard.Peer, updateTime time.Time) error { return errors.WithMessage(err, "failed to update WireGuard peer") } + peer.UID = fmt.Sprintf("u%x", md5.Sum([]byte(peer.PublicKey))) + // Update in database if err := s.peers.UpdatePeer(peer); err != nil { return errors.WithMessage(err, "failed to update peer") @@ -166,18 +163,8 @@ func (s *Server) UpdatePeer(peer wireguard.Peer, updateTime time.Time) error { // DeletePeer removes the peer from the physical WireGuard interface and the database. func (s *Server) DeletePeer(peer wireguard.Peer) error { - dev := s.peers.GetDevice(peer.DeviceName) - - var publicKey string - switch dev.Type { - case wireguard.DeviceTypeServer: - publicKey = peer.PublicKey - case wireguard.DeviceTypeClient: - publicKey = peer.EndpointPublicKey - } - // Delete WireGuard peer - if err := s.wg.RemovePeer(peer.DeviceName, publicKey); err != nil { + if err := s.wg.RemovePeer(peer.DeviceName, peer.PublicKey); err != nil { return errors.WithMessage(err, "failed to remove WireGuard peer") } diff --git a/internal/wireguard/peermanager.go b/internal/wireguard/peermanager.go index 56a8dfd..cf1abb0 100644 --- a/internal/wireguard/peermanager.go +++ b/internal/wireguard/peermanager.go @@ -88,10 +88,9 @@ type Peer struct { PersistentKeepalive int `form:"keepalive" binding:"gte=0"` // Misc. WireGuard Settings - EndpointPublicKey string `form:"endpointpubkey" binding:"required,base64"` // the public key of the remote endpoint - PrivateKey string `form:"privkey" binding:"omitempty,base64"` - IPsStr string `form:"ip" binding:"cidrlist,required_if=DeviceType server"` // a comma separated list of IPs of the client - DNSStr string `form:"dns" binding:"iplist"` // comma separated list of the DNS servers for the client + PrivateKey string `form:"privkey" binding:"omitempty,base64"` + IPsStr string `form:"ip" binding:"cidrlist,required_if=DeviceType server"` // a comma separated list of IPs of the client + DNSStr string `form:"dns" binding:"iplist"` // comma separated list of the DNS servers for the client // Global Device Settings (can be ignored, only make sense if device is in server mode) Mtu int `form:"mtu" binding:"gte=0,lte=1500"` @@ -126,14 +125,8 @@ func (p Peer) GetAllowedIPs() []string { return common.ParseStringList(p.AllowedIPsStr) } -func (p Peer) GetConfig(dev *Device) wgtypes.PeerConfig { - var publicKey wgtypes.Key - switch dev.Type { - case DeviceTypeServer: - publicKey, _ = wgtypes.ParseKey(p.PublicKey) - case DeviceTypeClient: - publicKey, _ = wgtypes.ParseKey(p.EndpointPublicKey) - } +func (p Peer) GetConfig(_ *Device) wgtypes.PeerConfig { + publicKey, _ := wgtypes.ParseKey(p.PublicKey) var presharedKey *wgtypes.Key if p.PresharedKey != "" { @@ -432,18 +425,11 @@ func (m *PeerManager) validateOrCreatePeer(device string, wgPeer wgtypes.Peer) e peer.PublicKey = wgPeer.PublicKey.String() peer.Identifier = "Autodetected Client (" + peer.PublicKey[0:8] + ")" } else if dev.Type == DeviceTypeClient { - // create a new key pair, not really needed but otherwise our "client exists" detection does not work... - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - return errors.Wrap(err, "failed to generate dummy private key") - } - peer.PrivateKey = key.String() - peer.PublicKey = key.PublicKey().String() - peer.EndpointPublicKey = wgPeer.PublicKey.String() + peer.PublicKey = wgPeer.PublicKey.String() if wgPeer.Endpoint != nil { peer.Endpoint = wgPeer.Endpoint.String() } - peer.Identifier = "Autodetected Endpoint (" + peer.EndpointPublicKey[0:8] + ")" + peer.Identifier = "Autodetected Endpoint (" + peer.PublicKey[0:8] + ")" } if wgPeer.PresharedKey != (wgtypes.Key{}) { peer.PresharedKey = wgPeer.PresharedKey.String() @@ -525,6 +511,7 @@ func (m *PeerManager) populatePeerData(peer *Peer) { } // fixPeerDefaultData tries to fill all required fields for the given peer +// also tries to migrate data if the database schema changed func (m *PeerManager) fixPeerDefaultData(peer *Peer, device *Device) error { updatePeer := false @@ -534,10 +521,6 @@ func (m *PeerManager) fixPeerDefaultData(peer *Peer, device *Device) error { peer.Endpoint = device.DefaultEndpoint updatePeer = true } - if peer.EndpointPublicKey == "" { - peer.EndpointPublicKey = device.PublicKey - updatePeer = true - } case DeviceTypeClient: } diff --git a/internal/wireguard/tpl/interface.tpl b/internal/wireguard/tpl/interface.tpl index f8aa3d2..318e2b7 100644 --- a/internal/wireguard/tpl/interface.tpl +++ b/internal/wireguard/tpl/interface.tpl @@ -52,14 +52,11 @@ PostDown = {{ .Interface.PostDown }} {{- if not .DeactivatedAt}} # -WGP- Peer: {{.Identifier}} / Updated: {{.UpdatedAt}} / Created: {{.CreatedAt}} # -WGP- Peer email: {{.Email}} +{{- if .PrivateKey}} # -WGP- PrivateKey: {{.PrivateKey}} +{{- end}} [Peer] -{{- if eq $.Interface.Type "server"}} PublicKey = {{ .PublicKey }} -{{- end}} -{{- if eq $.Interface.Type "client"}} -PublicKey = {{ .EndpointPublicKey }} -{{- end}} {{- if .PresharedKey}} PresharedKey = {{ .PresharedKey }} {{- end}} diff --git a/internal/wireguard/tpl/peer.tpl b/internal/wireguard/tpl/peer.tpl index 78c7fca..7f94732 100644 --- a/internal/wireguard/tpl/peer.tpl +++ b/internal/wireguard/tpl/peer.tpl @@ -17,7 +17,7 @@ MTU = {{.Peer.Mtu}} {{- end}} [Peer] -PublicKey = {{ .Peer.EndpointPublicKey }} +PublicKey = {{ .Peer.PublicKey }} Endpoint = {{ .Peer.Endpoint }} {{- if .Peer.AllowedIPsStr}} AllowedIPs = {{ .Peer.AllowedIPsStr }}