2023-09-19 14:45:49 +02:00
|
|
|
package wg
|
|
|
|
|
|
|
|
import (
|
2023-11-20 14:03:42 +01:00
|
|
|
"crypto"
|
|
|
|
"crypto/rand"
|
2023-10-28 17:38:25 +02:00
|
|
|
"fmt"
|
2023-09-19 14:45:49 +02:00
|
|
|
|
2024-01-02 00:55:50 +01:00
|
|
|
"github.com/tim-beatham/smegmesh/pkg/lib"
|
|
|
|
logging "github.com/tim-beatham/smegmesh/pkg/log"
|
2023-09-19 14:45:49 +02:00
|
|
|
"golang.zx2c4.com/wireguard/wgctrl"
|
|
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
|
|
)
|
|
|
|
|
2023-10-28 17:38:25 +02:00
|
|
|
type WgInterfaceManipulatorImpl struct {
|
|
|
|
client *wgctrl.Client
|
|
|
|
}
|
|
|
|
|
2023-11-20 14:03:42 +01:00
|
|
|
const hashLength = 6
|
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
// CreateInterface creates a WireGuard interface
|
2023-11-24 13:07:03 +01:00
|
|
|
func (m *WgInterfaceManipulatorImpl) CreateInterface(port int, privKey *wgtypes.Key) (string, error) {
|
2023-11-07 20:48:53 +01:00
|
|
|
rtnl, err := lib.NewRtNetlinkConfig()
|
|
|
|
|
|
|
|
if err != nil {
|
2023-11-20 14:03:42 +01:00
|
|
|
return "", fmt.Errorf("failed to access link: %w", err)
|
2023-11-07 20:48:53 +01:00
|
|
|
}
|
|
|
|
defer rtnl.Close()
|
|
|
|
|
2023-11-20 14:03:42 +01:00
|
|
|
randomBuf := make([]byte, 32)
|
|
|
|
_, err = rand.Read(randomBuf)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
md5 := crypto.MD5.New().Sum(randomBuf)
|
2023-12-07 19:18:13 +01:00
|
|
|
md5Str := fmt.Sprintf("wg%x", md5)[:hashLength]
|
2023-11-20 14:03:42 +01:00
|
|
|
|
|
|
|
err = rtnl.CreateLink(md5Str)
|
2023-09-19 14:45:49 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2023-11-20 14:03:42 +01:00
|
|
|
return "", fmt.Errorf("failed to create link: %w", err)
|
2023-09-19 14:45:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var cfg wgtypes.Config = wgtypes.Config{
|
2023-11-24 13:07:03 +01:00
|
|
|
PrivateKey: privKey,
|
2023-11-20 14:03:42 +01:00
|
|
|
ListenPort: &port,
|
2023-09-19 14:45:49 +02:00
|
|
|
}
|
|
|
|
|
2023-11-20 14:03:42 +01:00
|
|
|
err = m.client.ConfigureDevice(md5Str, cfg)
|
2023-10-28 17:38:25 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2023-11-20 14:03:42 +01:00
|
|
|
m.RemoveInterface(md5Str)
|
|
|
|
return "", fmt.Errorf("failed to configure dev: %w", err)
|
2023-10-28 17:38:25 +02:00
|
|
|
}
|
|
|
|
|
2023-11-20 14:03:42 +01:00
|
|
|
logging.Log.WriteInfof("ip link set up dev %s type wireguard", md5Str)
|
|
|
|
return md5Str, nil
|
2023-10-28 17:38:25 +02:00
|
|
|
}
|
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
// Add an address to the given interface
|
|
|
|
func (m *WgInterfaceManipulatorImpl) AddAddress(ifName string, addr string) error {
|
|
|
|
rtnl, err := lib.NewRtNetlinkConfig()
|
2023-10-28 17:38:25 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2023-11-07 20:48:53 +01:00
|
|
|
return fmt.Errorf("failed to create config: %w", err)
|
2023-09-21 19:43:29 +02:00
|
|
|
}
|
2023-11-07 20:48:53 +01:00
|
|
|
defer rtnl.Close()
|
2023-09-21 19:43:29 +02:00
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
err = rtnl.AddAddress(ifName, addr)
|
2023-11-01 11:39:46 +01:00
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
if err != nil {
|
|
|
|
err = fmt.Errorf("failed to add address: %w", err)
|
2023-11-01 11:39:46 +01:00
|
|
|
}
|
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveInterface implements WgInterfaceManipulator.
|
|
|
|
func (*WgInterfaceManipulatorImpl) RemoveInterface(ifName string) error {
|
|
|
|
rtnl, err := lib.NewRtNetlinkConfig()
|
2023-09-21 19:43:29 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2023-11-07 20:48:53 +01:00
|
|
|
return fmt.Errorf("failed to create config: %w", err)
|
2023-09-21 19:43:29 +02:00
|
|
|
}
|
2023-11-07 20:48:53 +01:00
|
|
|
defer rtnl.Close()
|
2023-09-21 19:43:29 +02:00
|
|
|
|
2023-11-07 20:48:53 +01:00
|
|
|
return rtnl.DeleteLink(ifName)
|
2023-09-21 19:43:29 +02:00
|
|
|
}
|
2023-10-28 17:38:25 +02:00
|
|
|
|
|
|
|
func NewWgInterfaceManipulator(client *wgctrl.Client) WgInterfaceManipulator {
|
|
|
|
return &WgInterfaceManipulatorImpl{client: client}
|
|
|
|
}
|