mirror of
https://github.com/psviderski/uncloud.git
synced 2026-10-08 22:24:54 +00:00
chore: move legacy unused WG tunnel and client connector to experiment/wg
This commit is contained in:
1 parent
e81e130544
commit
e9e7b3a61e
7 files changed
+45
-33
No files matched your search
@@ -0,0 +1,101 @@
|
||||
package wg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
|
||||
"github.com/psviderski/uncloud/internal/grpcversion"
|
||||
"github.com/psviderski/uncloud/internal/machine/constants"
|
||||
"github.com/psviderski/uncloud/internal/machine/network"
|
||||
"github.com/psviderski/uncloud/internal/secret"
|
||||
"golang.org/x/net/proxy"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
// Machine describes a remote machine that the experimental connector can reach.
|
||||
type Machine struct {
|
||||
Host string
|
||||
PublicKey secret.Secret
|
||||
}
|
||||
|
||||
type User interface {
|
||||
ManagementIP() netip.Addr
|
||||
PrivateKey() secret.Secret
|
||||
}
|
||||
|
||||
// WireGuardConnector establishes a connection to the cluster API through a WireGuard tunnel
|
||||
// to one of the cluster machines.
|
||||
type WireGuardConnector struct {
|
||||
user User
|
||||
machines []Machine
|
||||
tun *Tunnel
|
||||
}
|
||||
|
||||
func NewWireGuardConnector(user User, machines []Machine) *WireGuardConnector {
|
||||
return &WireGuardConnector{
|
||||
user: user,
|
||||
machines: machines,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle context cancellation.
|
||||
func (c *WireGuardConnector) Connect(ctx context.Context) (*grpc.ClientConn, error) {
|
||||
if len(c.machines) == 0 {
|
||||
return nil, fmt.Errorf("no machines to connect to")
|
||||
}
|
||||
// TODO: iterate over machines and try to connect to each one until successful.
|
||||
// For now, try to connect to only the first machine.
|
||||
machine := c.machines[0]
|
||||
endpointIPs, err := net.LookupIP(machine.Host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve IP for %q: %w", machine.Host, err)
|
||||
}
|
||||
endpointAddr, err := netip.ParseAddr(endpointIPs[0].String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse IP address %q: %w", endpointIPs[0].String(), err)
|
||||
}
|
||||
endpoint := netip.AddrPortFrom(endpointAddr, DefaultEndpointPort)
|
||||
machineManagementIP := network.ManagementIP(machine.PublicKey)
|
||||
machineAPIAddr := net.JoinHostPort(machineManagementIP.String(), strconv.Itoa(constants.MachineAPIPort))
|
||||
|
||||
tunCfg := &Config{
|
||||
LocalAddress: c.user.ManagementIP(),
|
||||
LocalPrivateKey: c.user.PrivateKey(),
|
||||
RemotePublicKey: machine.PublicKey,
|
||||
RemoteNetwork: netip.PrefixFrom(machineManagementIP, 128),
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
if c.tun, err = Connect(tunCfg); err != nil {
|
||||
return nil, fmt.Errorf("establish WireGuard tunnel to %q: %w", endpoint, err)
|
||||
}
|
||||
|
||||
conn, err := grpc.NewClient(
|
||||
machineAPIAddr,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
|
||||
return c.tun.DialContext(ctx, "tcp", addr)
|
||||
}),
|
||||
grpc.WithUnaryInterceptor(grpcversion.ClientUnaryInterceptor),
|
||||
grpc.WithStreamInterceptor(grpcversion.ClientStreamInterceptor),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("connect to machine API through WireGuard tunnel: %w", err)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (c *WireGuardConnector) Dialer() (proxy.ContextDialer, error) {
|
||||
return nil, fmt.Errorf("proxy connections not implemented for WireGuard connector")
|
||||
}
|
||||
|
||||
func (c *WireGuardConnector) Close() error {
|
||||
if c.tun != nil {
|
||||
c.tun.Close()
|
||||
c.tun = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package wg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/psviderski/uncloud/internal/secret"
|
||||
"golang.zx2c4.com/wireguard/conn"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultEndpointPort = 51820
|
||||
// DefaultKeepaliveInterval is a sensible interval that works with a wide variety of firewalls.
|
||||
DefaultKeepaliveInterval = 25 * time.Second
|
||||
)
|
||||
|
||||
type Tunnel struct {
|
||||
dev *device.Device
|
||||
net *netstack.Net
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
LocalAddress netip.Addr
|
||||
LocalPrivateKey secret.Secret
|
||||
Endpoint netip.AddrPort
|
||||
RemotePublicKey secret.Secret
|
||||
RemoteNetwork netip.Prefix
|
||||
DNS *netip.Addr
|
||||
MTU int
|
||||
KeepAlive time.Duration
|
||||
}
|
||||
|
||||
func Connect(config *Config) (*Tunnel, error) {
|
||||
var dns netip.Addr
|
||||
if config.DNS != nil {
|
||||
dns = *config.DNS
|
||||
} else {
|
||||
dns = netip.MustParseAddr("1.1.1.1")
|
||||
}
|
||||
mtu := config.MTU
|
||||
if mtu == 0 {
|
||||
mtu = device.DefaultMTU
|
||||
}
|
||||
keepAlive := config.KeepAlive
|
||||
if keepAlive == 0 {
|
||||
keepAlive = DefaultKeepaliveInterval
|
||||
}
|
||||
|
||||
tun, tnet, err := netstack.CreateNetTUN([]netip.Addr{config.LocalAddress}, []netip.Addr{dns}, mtu)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create WireGuard TUN device: %w", err)
|
||||
}
|
||||
|
||||
dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelError, "WireGuard tunnel: "))
|
||||
conf := fmt.Sprintf(
|
||||
"private_key=%s\n"+
|
||||
"public_key=%s\n"+
|
||||
"endpoint=%s\n"+
|
||||
"allowed_ip=%s\n"+
|
||||
"persistent_keepalive_interval=%d\n",
|
||||
config.LocalPrivateKey.String(),
|
||||
config.RemotePublicKey.String(),
|
||||
config.Endpoint.String(),
|
||||
config.RemoteNetwork.String(),
|
||||
int(keepAlive.Seconds()),
|
||||
)
|
||||
err = dev.IpcSet(conf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("configure WireGuard device: %w", err)
|
||||
}
|
||||
|
||||
err = dev.Up()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("enable WireGuard device: %w", err)
|
||||
}
|
||||
|
||||
return &Tunnel{
|
||||
dev: dev,
|
||||
net: tnet,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *Tunnel) Close() {
|
||||
if t.dev != nil {
|
||||
t.dev.Close()
|
||||
}
|
||||
t.dev, t.net = nil, nil
|
||||
}
|
||||
|
||||
func (t *Tunnel) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return t.net.DialContext(ctx, network, address)
|
||||
}
|
||||
Reference in new issue
Block a user