mirror of
https://github.com/tim-beatham/smegmesh.git
synced 2024-12-13 18:11:25 +01:00
b179cd3cf4
Hashing the interface and using ephmeral ports so that the admin doesn't choose an interface and port combination. An administrator can alteranatively decide to provide port but this isn't critical.
102 lines
2.2 KiB
Go
102 lines
2.2 KiB
Go
package wg
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
|
|
"github.com/tim-beatham/wgmesh/pkg/lib"
|
|
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
|
"golang.zx2c4.com/wireguard/wgctrl"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
)
|
|
|
|
type WgInterfaceManipulatorImpl struct {
|
|
client *wgctrl.Client
|
|
}
|
|
|
|
const hashLength = 6
|
|
|
|
// CreateInterface creates a WireGuard interface
|
|
func (m *WgInterfaceManipulatorImpl) CreateInterface(port int) (string, error) {
|
|
rtnl, err := lib.NewRtNetlinkConfig()
|
|
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to access link: %w", err)
|
|
}
|
|
defer rtnl.Close()
|
|
|
|
randomBuf := make([]byte, 32)
|
|
_, err = rand.Read(randomBuf)
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
md5 := crypto.MD5.New().Sum(randomBuf)
|
|
|
|
md5Str := fmt.Sprintf("wg%s", base64.StdEncoding.EncodeToString(md5)[:hashLength])
|
|
|
|
err = rtnl.CreateLink(md5Str)
|
|
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to create link: %w", err)
|
|
}
|
|
|
|
privateKey, err := wgtypes.GeneratePrivateKey()
|
|
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to create private key: %w", err)
|
|
}
|
|
|
|
var cfg wgtypes.Config = wgtypes.Config{
|
|
PrivateKey: &privateKey,
|
|
ListenPort: &port,
|
|
}
|
|
|
|
err = m.client.ConfigureDevice(md5Str, cfg)
|
|
|
|
if err != nil {
|
|
m.RemoveInterface(md5Str)
|
|
return "", fmt.Errorf("failed to configure dev: %w", err)
|
|
}
|
|
|
|
logging.Log.WriteInfof("ip link set up dev %s type wireguard", md5Str)
|
|
return md5Str, nil
|
|
}
|
|
|
|
// Add an address to the given interface
|
|
func (m *WgInterfaceManipulatorImpl) AddAddress(ifName string, addr string) error {
|
|
rtnl, err := lib.NewRtNetlinkConfig()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create config: %w", err)
|
|
}
|
|
defer rtnl.Close()
|
|
|
|
err = rtnl.AddAddress(ifName, addr)
|
|
|
|
if err != nil {
|
|
err = fmt.Errorf("failed to add address: %w", err)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// RemoveInterface implements WgInterfaceManipulator.
|
|
func (*WgInterfaceManipulatorImpl) RemoveInterface(ifName string) error {
|
|
rtnl, err := lib.NewRtNetlinkConfig()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create config: %w", err)
|
|
}
|
|
defer rtnl.Close()
|
|
|
|
return rtnl.DeleteLink(ifName)
|
|
}
|
|
|
|
func NewWgInterfaceManipulator(client *wgctrl.Client) WgInterfaceManipulator {
|
|
return &WgInterfaceManipulatorImpl{client: client}
|
|
}
|