This repository has been archived by the owner on Jul 5, 2021. It is now read-only.
forked from WireGuard/wgctrl-go
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2dcbbc4
commit d379964
Showing
5 changed files
with
136 additions
and
215 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,144 @@ | ||
// Command wgctrl is a testing utility for interacting with WireGuard via package | ||
// wgctrl. | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"net" | ||
"os" | ||
"strings" | ||
"text/template" | ||
"time" | ||
|
||
"github.com/alecthomas/kingpin" | ||
|
||
"golang.zx2c4.com/wireguard/wgctrl" | ||
"golang.zx2c4.com/wireguard/wgctrl/config" | ||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
c, err := wgctrl.New() | ||
if err != nil { | ||
log.Fatalf("failed to open wgctrl: %v", err) | ||
} | ||
defer c.Close() | ||
|
||
var devices []*wgtypes.Device | ||
if device := flag.Arg(0); device != "" { | ||
d, err := c.Device(device) | ||
if err != nil { | ||
log.Fatalf("failed to get device %q: %v", device, err) | ||
} | ||
|
||
devices = append(devices, d) | ||
} else { | ||
devices, err = c.Devices() | ||
if err != nil { | ||
log.Fatalf("failed to get devices: %v", err) | ||
} | ||
rootCmd := newCommandLine() | ||
getCmd, getOpt := newGetCommand(rootCmd) | ||
setCmd, setOpt := newSetCommand(rootCmd) | ||
switch kingpin.MustParse(rootCmd.Parse(os.Args[1:])) { | ||
case getCmd.FullCommand(): | ||
getConfig(*getOpt) | ||
case setCmd.FullCommand(): | ||
setConfig(*setOpt) | ||
} | ||
} | ||
|
||
for _, d := range devices { | ||
printDevice(d) | ||
func newCommandLine() *kingpin.Application { | ||
return kingpin.New("wgconf", "wireguard configuring tool") | ||
} | ||
|
||
for _, p := range d.Peers { | ||
printPeer(p) | ||
} | ||
} | ||
type getOption struct { | ||
Interface string | ||
ShowCredential bool | ||
} | ||
|
||
func printDevice(d *wgtypes.Device) { | ||
const f = `interface: %s (%s) | ||
public key: %s | ||
private key: (hidden) | ||
listening port: %d | ||
type setOption struct { | ||
Interface string | ||
Config string | ||
} | ||
|
||
` | ||
func newGetCommand(root *kingpin.Application) (*kingpin.CmdClause, *getOption) { | ||
opt := getOption{} | ||
cmd := root.Command("get", "get wireguard configuration") | ||
cmd.Flag("interface", "interface to show").StringVar(&opt.Interface) | ||
cmd.Flag("show-credential", "show credentials for interface").BoolVar(&opt.ShowCredential) | ||
return cmd, &opt | ||
} | ||
|
||
fmt.Printf( | ||
f, | ||
d.Name, | ||
d.Type.String(), | ||
d.PublicKey.String(), | ||
d.ListenPort) | ||
func newSetCommand(root *kingpin.Application) (*kingpin.CmdClause, *setOption) { | ||
opt := setOption{} | ||
cmd := root.Command("set", "set wireguard configuration") | ||
cmd.Flag("interface", "interface to set").StringVar(&opt.Interface) | ||
cmd.Flag("config", "configuration file").StringVar(&opt.Config) | ||
return cmd, &opt | ||
} | ||
|
||
func printPeer(p wgtypes.Peer) { | ||
const f = `peer: %s | ||
endpoint: %s | ||
allowed ips: %s | ||
latest handshake: %s | ||
transfer: %d B received, %d B sent | ||
func checkError(err error) { | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
} | ||
|
||
` | ||
func getConfig(opt getOption) { | ||
|
||
client, err := wgctrl.New() | ||
checkError(err) | ||
dev, err := client.Device(opt.Interface) | ||
checkError(err) | ||
fmt.Printf("Interface: %s (%s)\n", opt.Interface, dev.Type.String()) | ||
fmt.Printf(" public key: %s\n", dev.PublicKey.String()) | ||
privkeyStr := "(hidden)" | ||
if opt.ShowCredential { | ||
privkeyStr = dev.PrivateKey.String() | ||
} | ||
fmt.Printf(" private key: %s\n", privkeyStr) | ||
fmt.Printf(" listening port: %d\n", dev.ListenPort) | ||
for _, peer := range dev.Peers { | ||
printPeer(peer, opt.ShowCredential) | ||
} | ||
} | ||
|
||
fmt.Printf( | ||
f, | ||
p.PublicKey.String(), | ||
// TODO(mdlayher): get right endpoint with getnameinfo. | ||
p.Endpoint.String(), | ||
ipsString(p.AllowedIPs), | ||
p.LastHandshakeTime.String(), | ||
p.ReceiveBytes, | ||
p.TransmitBytes, | ||
) | ||
func setConfig(opt setOption) { | ||
fin, err := os.Open(opt.Config) | ||
checkError(err) | ||
cfg, err := config.LoadConfig(fin) | ||
checkError(err) | ||
client, err := wgctrl.New() | ||
checkError(err) | ||
err = client.ConfigureDevice(opt.Interface, *cfg) | ||
checkError(err) | ||
log.Printf("interface %s configured.\n", opt.Interface) | ||
} | ||
|
||
func ipsString(ipns []net.IPNet) string { | ||
ss := make([]string, 0, len(ipns)) | ||
for _, ipn := range ipns { | ||
ss = append(ss, ipn.String()) | ||
func printPeer(peer wgtypes.Peer, showCredential bool) { | ||
const tmpl = ` | ||
peer: {{ .PublicKey }} | ||
preshared key = {{ .PresharedKey }} | ||
endpoint = {{ .Endpoint }} | ||
keep alive interval = {{ .KeepAliveInterval }}s | ||
last handshake time = {{ .LastHandshakeTime }} | ||
receive bytes = {{ .ReceiveBytes }} | ||
transmit bytes = {{ .TransmitBytes }} | ||
allowed ips = {{ .AllowedIPs }} | ||
protocol version = {{ .ProtocolVersion }} | ||
` | ||
|
||
type tmplContent struct { | ||
PublicKey string | ||
PresharedKey string | ||
Endpoint string | ||
KeepAliveInterval float64 | ||
LastHandshakeTime string | ||
ReceiveBytes int64 | ||
TransmitBytes int64 | ||
AllowedIPs string | ||
ProtocolVersion int | ||
} | ||
|
||
t := template.Must(template.New("peer_tmpl").Parse(tmpl)) | ||
c := tmplContent{ | ||
PublicKey: peer.PublicKey.String(), | ||
PresharedKey: "(hidden)", | ||
Endpoint: peer.Endpoint.String(), | ||
KeepAliveInterval: peer.PersistentKeepaliveInterval.Seconds(), | ||
LastHandshakeTime: peer.LastHandshakeTime.Format(time.RFC3339), | ||
ReceiveBytes: peer.ReceiveBytes, | ||
TransmitBytes: peer.TransmitBytes, | ||
AllowedIPs: "", | ||
ProtocolVersion: peer.ProtocolVersion, | ||
} | ||
|
||
return strings.Join(ss, ", ") | ||
if showCredential { | ||
c.PresharedKey = peer.PresharedKey.String() | ||
} | ||
allowdIpStrings := make([]string, 0, len(peer.AllowedIPs)) | ||
for _, v := range peer.AllowedIPs { | ||
allowdIpStrings = append(allowdIpStrings, v.String()) | ||
} | ||
c.AllowedIPs = strings.Join(allowdIpStrings, ", ") | ||
t.Execute(os.Stdout, c) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.