mirror of
https://github.com/h44z/wg-portal.git
synced 2025-10-07 08:56:18 +00:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d978fd560d | ||
|
ec60dd136a | ||
|
6fd4089766 | ||
|
4dd7f7b14b | ||
|
10defaa2ba |
@@ -37,7 +37,7 @@ RUN apt-get update && apt-get upgrade -y && \
|
|||||||
chmod +rx /usr/local/bin/goss && \
|
chmod +rx /usr/local/bin/goss && \
|
||||||
goss --version
|
goss --version
|
||||||
|
|
||||||
COPY --from=builder /build/dist/wg-portal /app/wgportal
|
COPY --from=builder /build/dist/wg-portal-amd64 /app/wgportal
|
||||||
COPY --from=builder /build/dist/assets /app/assets
|
COPY --from=builder /build/dist/assets /app/assets
|
||||||
COPY --from=builder /build/scripts /app/
|
COPY --from=builder /build/scripts /app/
|
||||||
|
|
||||||
|
@@ -31,6 +31,8 @@ The compiled binary and all necessary assets will be located in the dist folder.
|
|||||||
- ExecStart
|
- ExecStart
|
||||||
- EnvironmentFile
|
- EnvironmentFile
|
||||||
- Update environment variables in the `wg-portal.env` file to fit your needs
|
- Update environment variables in the `wg-portal.env` file to fit your needs
|
||||||
|
- Make sure that the binary application file is executable
|
||||||
|
- `sudo chmod +x /opt/wg-portal/wg-portal-*`
|
||||||
- Link the system service file to the correct folder:
|
- Link the system service file to the correct folder:
|
||||||
- `sudo ln -s /opt/wg-portal/wg-portal.service /etc/systemd/system/wg-portal.service`
|
- `sudo ln -s /opt/wg-portal/wg-portal.service /etc/systemd/system/wg-portal.service`
|
||||||
- Reload the systemctl daemon:
|
- Reload the systemctl daemon:
|
||||||
|
@@ -85,7 +85,7 @@ A detailed description for using this software with a raspberry pi can be found
|
|||||||
## What is out of scope
|
## What is out of scope
|
||||||
|
|
||||||
* Generation or application of any `iptables` or `nftables` rules
|
* Generation or application of any `iptables` or `nftables` rules
|
||||||
* Setting up or changing IP-addresses of the WireGuard interface
|
* Setting up or changing IP-addresses of the WireGuard interface on operating systems other than linux
|
||||||
|
|
||||||
## Application stack
|
## Application stack
|
||||||
|
|
||||||
|
@@ -66,3 +66,8 @@ pre{background:#f7f7f9}iframe{overflow:hidden;border:none}@media (min-width: 768
|
|||||||
margin: -4px 5px 5px 0;
|
margin: -4px 5px 5px 0;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-group.required label:after {
|
||||||
|
content:"*";
|
||||||
|
color:red;
|
||||||
|
}
|
@@ -21,13 +21,13 @@
|
|||||||
{{template "prt_flashes.html" .}}
|
{{template "prt_flashes.html" .}}
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputEmail">Email Addresses</label>
|
<label for="inputEmail">Email Addresses</label>
|
||||||
<input type="text" name="email" class="form-control" id="inputEmail" value="{{.FormData.Emails}}">
|
<input type="text" name="email" class="form-control" id="inputEmail" value="{{.FormData.Emails}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputIdentifier">Client Friendly Name (will be added as suffix to the name of the user)</label>
|
<label for="inputIdentifier">Client Friendly Name (will be added as suffix to the name of the user)</label>
|
||||||
<input type="text" name="identifier" class="form-control" id="inputIdentifier" value="{{.FormData.Identifier}}">
|
<input type="text" name="identifier" class="form-control" id="inputIdentifier" value="{{.FormData.Identifier}}">
|
||||||
</div>
|
</div>
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputServerPublicKey">Public Key</label>
|
<label for="inputServerPublicKey">Public Key</label>
|
||||||
<input type="text" name="pubkey" class="form-control" id="inputServerPublicKey" value="{{.Peer.PublicKey}}">
|
<input type="text" name="pubkey" class="form-control" id="inputServerPublicKey" value="{{.Peer.PublicKey}}">
|
||||||
</div>
|
</div>
|
||||||
@@ -53,25 +53,25 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputIdentifier">Client Friendly Name</label>
|
<label for="inputIdentifier">Client Friendly Name</label>
|
||||||
<input type="text" name="identifier" class="form-control" id="inputIdentifier" value="{{.Peer.Identifier}}">
|
<input type="text" name="identifier" class="form-control" id="inputIdentifier" value="{{.Peer.Identifier}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputEmail">Client Email Address</label>
|
<label for="inputEmail">Client Email Address</label>
|
||||||
<input type="email" name="mail" class="form-control" id="inputEmail" value="{{.Peer.Email}}">
|
<input type="email" name="mail" class="form-control" id="inputEmail" value="{{.Peer.Email}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputIP">Client IP Address</label>
|
<label for="inputIP">Client IP Address</label>
|
||||||
<input type="text" name="ip" class="form-control" id="inputIP" value="{{.Peer.IPsStr}}">
|
<input type="text" name="ip" class="form-control" id="inputIP" value="{{.Peer.IPsStr}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputAllowedIP">Allowed IPs</label>
|
<label for="inputAllowedIP">Allowed IPs</label>
|
||||||
<input type="text" name="allowedip" class="form-control" id="inputAllowedIP" value="{{.Peer.AllowedIPsStr}}">
|
<input type="text" name="allowedip" class="form-control" id="inputAllowedIP" value="{{.Peer.AllowedIPsStr}}">
|
||||||
</div>
|
</div>
|
||||||
|
@@ -18,27 +18,42 @@
|
|||||||
|
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="device" value="{{.Device.DeviceName}}">
|
<input type="hidden" name="device" value="{{.Device.DeviceName}}">
|
||||||
<input type="hidden" name="privkey" value="{{.Device.PrivateKey}}">
|
|
||||||
<h3>Server's interface configuration</h3>
|
<h3>Server's interface configuration</h3>
|
||||||
|
{{if .EditableKeys}}
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group required col-md-12">
|
||||||
|
<label for="inputServerPrivateKey">Private Key</label>
|
||||||
|
<input type="text" name="privkey" class="form-control" id="inputServerPrivateKey" value="{{.Device.PrivateKey}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group required col-md-12">
|
||||||
|
<label for="inputServerPublicKey">Public Key</label>
|
||||||
|
<input type="text" name="pubkey" class="form-control" id="inputServerPublicKey" value="{{.Device.PublicKey}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<input type="hidden" name="privkey" value="{{.Device.PrivateKey}}">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group col-md-12">
|
||||||
<label for="inputServerPublicKey">Public Key</label>
|
<label for="inputServerPublicKey">Public Key</label>
|
||||||
<input type="text" name="pubkey" readonly class="form-control" id="inputServerPublicKey" value="{{.Device.PublicKey}}">
|
<input type="text" name="pubkey" readonly class="form-control" id="inputServerPublicKey" value="{{.Device.PublicKey}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group required col-md-6">
|
||||||
<label for="inputListenPort">Listen port</label>
|
<label for="inputListenPort">Listen port</label>
|
||||||
<input type="number" name="port" class="form-control" id="inputListenPort" placeholder="51820" value="{{.Device.ListenPort}}">
|
<input type="number" name="port" class="form-control" id="inputListenPort" placeholder="51820" value="{{.Device.ListenPort}}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-6">
|
<div class="form-group required col-md-6">
|
||||||
<label for="inputIPs">Server IP address</label>
|
<label for="inputIPs">Server IP address</label>
|
||||||
<input type="text" name="ip" class="form-control" id="inputIPs" placeholder="10.6.6.1/24" value="{{.Device.IPsStr}}">
|
<input type="text" name="ip" class="form-control" id="inputIPs" placeholder="10.6.6.1/24" value="{{.Device.IPsStr}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3>Client's global configuration</h3>
|
<h3>Client's global configuration</h3>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group col-md-12">
|
<div class="form-group required col-md-12">
|
||||||
<label for="inputPublicEndpoint">Public Enpoint for Clients</label>
|
<label for="inputPublicEndpoint">Public Enpoint for Clients</label>
|
||||||
<input type="text" name="endpoint" class="form-control" id="inputPublicEndpoint" placeholder="vpn.company.com:51820" value="{{.Device.Endpoint}}">
|
<input type="text" name="endpoint" class="form-control" id="inputPublicEndpoint" placeholder="vpn.company.com:51820" value="{{.Device.Endpoint}}">
|
||||||
</div>
|
</div>
|
||||||
|
1
go.mod
1
go.mod
@@ -10,6 +10,7 @@ require (
|
|||||||
github.com/gorilla/sessions v1.2.1 // indirect
|
github.com/gorilla/sessions v1.2.1 // indirect
|
||||||
github.com/jordan-wright/email v4.0.1-0.20200917010138-e1c00e156980+incompatible
|
github.com/jordan-wright/email v4.0.1-0.20200917010138-e1c00e156980+incompatible
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
|
github.com/milosgajdos/tenus v0.0.3
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/h44z/wg-portal/internal/wireguard"
|
"github.com/h44z/wg-portal/internal/wireguard"
|
||||||
|
|
||||||
@@ -91,6 +92,7 @@ func NewConfig() *Config {
|
|||||||
cfg.LDAP.BindPass = "SuperSecret"
|
cfg.LDAP.BindPass = "SuperSecret"
|
||||||
cfg.WG.DeviceName = "wg0"
|
cfg.WG.DeviceName = "wg0"
|
||||||
cfg.WG.WireGuardConfig = "/etc/wireguard/wg0.conf"
|
cfg.WG.WireGuardConfig = "/etc/wireguard/wg0.conf"
|
||||||
|
cfg.WG.ManageIPAddresses = true
|
||||||
cfg.AdminLdapGroup = "CN=WireGuardAdmins,OU=_O_IT,DC=COMPANY,DC=LOCAL"
|
cfg.AdminLdapGroup = "CN=WireGuardAdmins,OU=_O_IT,DC=COMPANY,DC=LOCAL"
|
||||||
cfg.Email.Host = "127.0.0.1"
|
cfg.Email.Host = "127.0.0.1"
|
||||||
cfg.Email.Port = 25
|
cfg.Email.Port = 25
|
||||||
@@ -109,5 +111,10 @@ func NewConfig() *Config {
|
|||||||
log.Warnf("unable to load environment config: %v", err)
|
log.Warnf("unable to load environment config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cfg.WG.ManageIPAddresses && runtime.GOOS != "linux" {
|
||||||
|
log.Warnf("Managing IP addresses only works on linux! Feature disabled.")
|
||||||
|
cfg.WG.ManageIPAddresses = false
|
||||||
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
@@ -19,19 +19,21 @@ func (s *Server) GetAdminEditInterface(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "admin_edit_interface.html", struct {
|
c.HTML(http.StatusOK, "admin_edit_interface.html", struct {
|
||||||
Route string
|
Route string
|
||||||
Alerts []FlashData
|
Alerts []FlashData
|
||||||
Session SessionData
|
Session SessionData
|
||||||
Static StaticData
|
Static StaticData
|
||||||
Peers []User
|
Peers []User
|
||||||
Device Device
|
Device Device
|
||||||
|
EditableKeys bool
|
||||||
}{
|
}{
|
||||||
Route: c.Request.URL.Path,
|
Route: c.Request.URL.Path,
|
||||||
Alerts: s.getFlashes(c),
|
Alerts: s.getFlashes(c),
|
||||||
Session: currentSession,
|
Session: currentSession,
|
||||||
Static: s.getStaticData(),
|
Static: s.getStaticData(),
|
||||||
Peers: users,
|
Peers: users,
|
||||||
Device: currentSession.FormData.(Device),
|
Device: currentSession.FormData.(Device),
|
||||||
|
EditableKeys: s.config.Core.EditableKeys,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +84,24 @@ func (s *Server) PostAdminEditInterface(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update interface IP address
|
||||||
|
if s.config.WG.ManageIPAddresses {
|
||||||
|
if err := s.wg.SetIPAddress(formDevice.IPs); err != nil {
|
||||||
|
_ = s.updateFormInSession(c, formDevice)
|
||||||
|
s.setFlashMessage(c, "Failed to update ip address: "+err.Error(), "danger")
|
||||||
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit?formerr=update")
|
||||||
|
}
|
||||||
|
if err := s.wg.SetMTU(formDevice.Mtu); err != nil {
|
||||||
|
_ = s.updateFormInSession(c, formDevice)
|
||||||
|
s.setFlashMessage(c, "Failed to update MTU: "+err.Error(), "danger")
|
||||||
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit?formerr=update")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s.setFlashMessage(c, "Changes applied successfully!", "success")
|
s.setFlashMessage(c, "Changes applied successfully!", "success")
|
||||||
s.setFlashMessage(c, "WireGuard must be restarted to apply ip changes.", "warning")
|
if !s.config.WG.ManageIPAddresses {
|
||||||
|
s.setFlashMessage(c, "WireGuard must be restarted to apply ip changes.", "warning")
|
||||||
|
}
|
||||||
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
c.Redirect(http.StatusSeeOther, "/admin/device/edit")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -202,7 +202,7 @@ type Device struct {
|
|||||||
Interface *wgtypes.Device `gorm:"-"`
|
Interface *wgtypes.Device `gorm:"-"`
|
||||||
|
|
||||||
DeviceName string `form:"device" gorm:"primaryKey" binding:"required,alphanum"`
|
DeviceName string `form:"device" gorm:"primaryKey" binding:"required,alphanum"`
|
||||||
PrivateKey string `form:"privkey" binding:"base64"`
|
PrivateKey string `form:"privkey" binding:"required,base64"`
|
||||||
PublicKey string `form:"pubkey" binding:"required,base64"`
|
PublicKey string `form:"pubkey" binding:"required,base64"`
|
||||||
PersistentKeepalive int `form:"keepalive" binding:"gte=0"`
|
PersistentKeepalive int `form:"keepalive" binding:"gte=0"`
|
||||||
ListenPort int `form:"port" binding:"required,gt=0"`
|
ListenPort int `form:"port" binding:"required,gt=0"`
|
||||||
@@ -319,6 +319,18 @@ func (u *UserManager) InitFromCurrentInterface() error {
|
|||||||
log.Errorf("failed to init user-manager from device: %v", err)
|
log.Errorf("failed to init user-manager from device: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
var ipAddresses []string
|
||||||
|
var mtu int
|
||||||
|
if u.wg.Cfg.ManageIPAddresses {
|
||||||
|
if ipAddresses, err = u.wg.GetIPAddress(); err != nil {
|
||||||
|
log.Errorf("failed to init user-manager from device: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if mtu, err = u.wg.GetMTU(); err != nil {
|
||||||
|
log.Errorf("failed to init user-manager from device: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if entries already exist in database, if not create them
|
// Check if entries already exist in database, if not create them
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
@@ -326,7 +338,7 @@ func (u *UserManager) InitFromCurrentInterface() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := u.validateOrCreateDevice(*device); err != nil {
|
if err := u.validateOrCreateDevice(*device, ipAddresses, mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +378,7 @@ func (u *UserManager) validateOrCreateUserForPeer(peer wgtypes.Peer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserManager) validateOrCreateDevice(dev wgtypes.Device) error {
|
func (u *UserManager) validateOrCreateDevice(dev wgtypes.Device, ipAddresses []string, mtu int) error {
|
||||||
device := Device{}
|
device := Device{}
|
||||||
u.db.Where("device_name = ?", dev.Name).FirstOrInit(&device)
|
u.db.Where("device_name = ?", dev.Name).FirstOrInit(&device)
|
||||||
|
|
||||||
@@ -377,6 +389,11 @@ func (u *UserManager) validateOrCreateDevice(dev wgtypes.Device) error {
|
|||||||
device.ListenPort = dev.ListenPort
|
device.ListenPort = dev.ListenPort
|
||||||
device.Mtu = 0
|
device.Mtu = 0
|
||||||
device.PersistentKeepalive = 16 // Default
|
device.PersistentKeepalive = 16 // Default
|
||||||
|
device.IPsStr = strings.Join(ipAddresses, ", ")
|
||||||
|
if mtu == wireguard.WireGuardDefaultMTU {
|
||||||
|
mtu = 0
|
||||||
|
}
|
||||||
|
device.Mtu = mtu
|
||||||
|
|
||||||
res := u.db.Create(&device)
|
res := u.db.Create(&device)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package wireguard
|
package wireguard
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DeviceName string `yaml:"device" envconfig:"WG_DEVICE"`
|
DeviceName string `yaml:"device" envconfig:"WG_DEVICE"`
|
||||||
WireGuardConfig string `yaml:"configFile" envconfig:"WG_CONFIG_FILE"` // optional, if set, updates will be written to this file
|
WireGuardConfig string `yaml:"configFile" envconfig:"WG_CONFIG_FILE"` // optional, if set, updates will be written to this file
|
||||||
|
ManageIPAddresses bool `yaml:"manageIPAddresses" envconfig:"MANAGE_IPS"` // handle ip-address setup of interface
|
||||||
}
|
}
|
||||||
|
120
internal/wireguard/net.go
Normal file
120
internal/wireguard/net.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package wireguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/milosgajdos/tenus"
|
||||||
|
)
|
||||||
|
|
||||||
|
const WireGuardDefaultMTU = 1420
|
||||||
|
|
||||||
|
func (m *Manager) GetIPAddress() ([]string, error) {
|
||||||
|
wgInterface, err := tenus.NewLinkFrom(m.Cfg.DeviceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not retrieve WireGuard interface %s: %w", m.Cfg.DeviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get golang net.interface
|
||||||
|
iface := wgInterface.NetInterface()
|
||||||
|
if iface == nil { // Not sure if this check is really necessary
|
||||||
|
return nil, fmt.Errorf("could not retrieve WireGuard net.interface: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not retrieve WireGuard ip addresses: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipAddresses := make([]string, 0, len(addrs))
|
||||||
|
for _, addr := range addrs {
|
||||||
|
var ip net.IP
|
||||||
|
var mask net.IPMask
|
||||||
|
switch v := addr.(type) {
|
||||||
|
case *net.IPNet:
|
||||||
|
ip = v.IP
|
||||||
|
mask = v.Mask
|
||||||
|
case *net.IPAddr:
|
||||||
|
ip = v.IP
|
||||||
|
mask = ip.DefaultMask()
|
||||||
|
}
|
||||||
|
if ip == nil {
|
||||||
|
continue // something is wrong?
|
||||||
|
}
|
||||||
|
|
||||||
|
maskSize, _ := mask.Size()
|
||||||
|
cidr := fmt.Sprintf("%s/%d", ip.String(), maskSize)
|
||||||
|
ipAddresses = append(ipAddresses, cidr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipAddresses, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) SetIPAddress(cidrs []string) error {
|
||||||
|
wgInterface, err := tenus.NewLinkFrom(m.Cfg.DeviceName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not retrieve WireGuard interface %s: %w", m.Cfg.DeviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First remove existing IP addresses
|
||||||
|
existingIPs, err := m.GetIPAddress()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, cidr := range existingIPs {
|
||||||
|
wgIp, wgIpNet, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse cidr %s: %w", cidr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := wgInterface.UnsetLinkIp(wgIp, wgIpNet); err != nil {
|
||||||
|
return fmt.Errorf("failed to unset ip %s: %w", cidr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next set new IP adrresses
|
||||||
|
for _, cidr := range cidrs {
|
||||||
|
wgIp, wgIpNet, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse cidr %s: %w", cidr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := wgInterface.SetLinkIp(wgIp, wgIpNet); err != nil {
|
||||||
|
return fmt.Errorf("failed to set ip %s: %w", cidr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) GetMTU() (int, error) {
|
||||||
|
wgInterface, err := tenus.NewLinkFrom(m.Cfg.DeviceName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not retrieve WireGuard interface %s: %w", m.Cfg.DeviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get golang net.interface
|
||||||
|
iface := wgInterface.NetInterface()
|
||||||
|
if iface == nil { // Not sure if this check is really necessary
|
||||||
|
return 0, fmt.Errorf("could not retrieve WireGuard net.interface: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return iface.MTU, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) SetMTU(mtu int) error {
|
||||||
|
wgInterface, err := tenus.NewLinkFrom(m.Cfg.DeviceName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not retrieve WireGuard interface %s: %w", m.Cfg.DeviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mtu == 0 {
|
||||||
|
mtu = WireGuardDefaultMTU
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := wgInterface.SetLinkMTU(mtu); err != nil {
|
||||||
|
return fmt.Errorf("could not set MTU on interface %s: %w", m.Cfg.DeviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user