mirror of
https://codeberg.org/cunicu/cunicu.git
synced 2025-10-04 00:16:44 +08:00
167 lines
3.3 KiB
Go
167 lines
3.3 KiB
Go
package wg
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/stv0g/cunicu/pkg/crypto"
|
|
"github.com/stv0g/cunicu/pkg/util"
|
|
t "github.com/stv0g/cunicu/pkg/util/terminal"
|
|
"golang.org/x/exp/slices"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
)
|
|
|
|
type Device wgtypes.Device
|
|
|
|
type DeviceList []*wgtypes.Device
|
|
|
|
func (devs *DeviceList) GetByName(name string) *wgtypes.Device {
|
|
for _, dev := range *devs {
|
|
if dev.Name == name {
|
|
return dev
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *Device) DumpEnv(wr io.Writer) error {
|
|
var color, hideKeys bool
|
|
|
|
switch os.Getenv("WG_COLOR_MODE") {
|
|
case "always":
|
|
color = true
|
|
case "never":
|
|
color = false
|
|
case "auto":
|
|
fallthrough
|
|
default:
|
|
color = t.IsATTY(os.Stdout)
|
|
}
|
|
|
|
if !color {
|
|
wr = t.NewANSIStripper(wr)
|
|
}
|
|
|
|
switch os.Getenv("WG_HIDE_KEYS") {
|
|
case "never":
|
|
hideKeys = false
|
|
case "always":
|
|
fallthrough
|
|
default:
|
|
hideKeys = true
|
|
}
|
|
|
|
return d.Dump(wr, hideKeys)
|
|
}
|
|
|
|
func (d *Device) Dump(wr io.Writer, hideKeys bool) error {
|
|
wri := t.NewIndenter(wr, " ")
|
|
|
|
fmt.Fprintf(wr, t.Mods("interface", t.Bold, t.FgGreen)+": "+t.Mods("%s", t.FgGreen)+"\n", d.Name)
|
|
|
|
if crypto.Key(d.PrivateKey).IsSet() {
|
|
t.FprintKV(wri, "public key", d.PublicKey)
|
|
|
|
if hideKeys {
|
|
t.FprintKV(wri, "private key", "(hidden)")
|
|
} else {
|
|
t.FprintKV(wri, "private key", d.PrivateKey)
|
|
}
|
|
}
|
|
|
|
t.FprintKV(wri, "listening port", d.ListenPort)
|
|
|
|
if d.FirewallMark > 0 {
|
|
t.FprintKV(wri, "fwmark", fmt.Sprintf("%d", d.FirewallMark))
|
|
}
|
|
|
|
// Sort peers by last handshake time
|
|
slices.SortFunc(d.Peers, func(a, b wgtypes.Peer) bool {
|
|
return CmpPeerHandshakeTime(a, b) < 0
|
|
})
|
|
|
|
for _, p := range d.Peers {
|
|
fmt.Fprintf(wr, "\n"+t.Mods("peer", t.Bold, t.FgYellow)+": "+t.Mods("%s", t.FgYellow)+"\n", p.PublicKey)
|
|
|
|
if crypto.Key(p.PresharedKey).IsSet() {
|
|
if hideKeys {
|
|
t.FprintKV(wri, "preshared key", "(hidden)")
|
|
} else {
|
|
t.FprintKV(wri, "preshared key", p.PresharedKey)
|
|
}
|
|
}
|
|
|
|
if p.Endpoint != nil {
|
|
t.FprintKV(wri, "endpoint", p.Endpoint)
|
|
}
|
|
|
|
if !p.LastHandshakeTime.IsZero() {
|
|
t.FprintKV(wri, "latest handshake", util.Ago(p.LastHandshakeTime))
|
|
}
|
|
|
|
if len(p.AllowedIPs) > 0 {
|
|
allowedIPs := []string{}
|
|
for _, allowedIP := range p.AllowedIPs {
|
|
allowedIPs = append(allowedIPs, allowedIP.String())
|
|
}
|
|
|
|
t.FprintKV(wri, "allowed ips", strings.Join(allowedIPs, ", "))
|
|
} else {
|
|
t.FprintKV(wri, "allowed ips", "(none)")
|
|
}
|
|
|
|
if p.ReceiveBytes > 0 || p.TransmitBytes > 0 {
|
|
t.FprintKV(wri, "transfer", fmt.Sprintf("%s received, %s sent",
|
|
util.PrettyBytes(p.ReceiveBytes),
|
|
util.PrettyBytes(p.TransmitBytes)))
|
|
}
|
|
|
|
if p.PersistentKeepaliveInterval > 0 {
|
|
t.FprintKV(wri, "persistent keepalive", util.Every(p.PersistentKeepaliveInterval))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *Device) Config() *Config {
|
|
cfg := &Config{}
|
|
|
|
if crypto.Key(d.PrivateKey).IsSet() {
|
|
cfg.PrivateKey = &d.PrivateKey
|
|
}
|
|
|
|
if d.ListenPort != 0 {
|
|
cfg.ListenPort = &d.ListenPort
|
|
}
|
|
|
|
if d.FirewallMark != 0 {
|
|
cfg.FirewallMark = &d.FirewallMark
|
|
}
|
|
|
|
for _, p := range d.Peers {
|
|
p := p
|
|
|
|
pcfg := wgtypes.PeerConfig{
|
|
PublicKey: p.PublicKey,
|
|
Endpoint: p.Endpoint,
|
|
AllowedIPs: p.AllowedIPs,
|
|
}
|
|
|
|
if crypto.Key(p.PresharedKey).IsSet() {
|
|
pcfg.PresharedKey = &p.PresharedKey
|
|
}
|
|
|
|
if pki := p.PersistentKeepaliveInterval; pki > 0 {
|
|
pcfg.PersistentKeepaliveInterval = &pki
|
|
}
|
|
|
|
cfg.Peers = append(cfg.Peers, pcfg)
|
|
}
|
|
|
|
return cfg
|
|
}
|