Skip to content

Commit

Permalink
feat: add --wireguard-key-file param (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
deansheather authored Mar 9, 2023
1 parent 0658062 commit 16be491
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ go.work

# Build directory.
build/

*.key
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ build: build/tunneld build/tunnel
# architecture. You can change the architecture by setting GOOS and GOARCH
# manually before calling this target.
build/tunneld build/tunnel: build/%: $(shell find . -type f -name '*.go')
go build \
CGO_ENABLED=0 go build \
-o "$@" \
-tags urfave_cli_no_docs \
-ldflags "-s -w -X 'github.com/coder/wgtunnel/buildinfo.tag=$(VERSION)'" \
Expand Down
51 changes: 44 additions & 7 deletions cmd/tunneld/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,15 @@ func main() {
&cli.StringFlag{
Name: "wireguard-key",
Aliases: []string{"wg-key"},
Usage: "The private key for the wireguard server. It should be base64 encoded.",
Usage: "The private key for the wireguard server. It should be base64 encoded. You can generate a key with `wg genkey`. Mutually exclusive with wireguard-key-file.",
EnvVars: []string{"TUNNELD_WIREGUARD_KEY"},
},
&cli.StringFlag{
Name: "wireguard-key-file",
Aliases: []string{"wg-key-file"},
Usage: "The file path containing the private key for the wireguard server. The contents should be base64 encoded. If the file does not exist, a key will be generated for you and written to the file. Mutually exclusive with wireguard-key.",
EnvVars: []string{"TUNNELD_WIREGUARD_KEY_FILE"},
},
&cli.IntFlag{
Name: "wireguard-mtu",
Aliases: []string{"wg-mtu"},
Expand Down Expand Up @@ -127,24 +133,28 @@ func runApp(ctx *cli.Context) error {
wireguardEndpoint = ctx.String("wireguard-endpoint")
wireguardPort = ctx.Uint("wireguard-port")
wireguardKey = ctx.String("wireguard-key")
wireguardKeyFile = ctx.String("wireguard-key-file")
wireguardMTU = ctx.Int("wireguard-mtu")
wireguardServerIP = ctx.String("wireguard-server-ip")
wireguardNetworkPrefix = ctx.String("wireguard-network-prefix")
pprofListenAddress = ctx.String("pprof-listen-address")
tracingHoneycombTeam = ctx.String("tracing-honeycomb-team")
)
if baseURL == "" {
return xerrors.New("base-hostname is required. See --help for more information.")
return xerrors.New("base-url is required. See --help for more information.")
}
if wireguardEndpoint == "" {
return xerrors.New("wireguard-endpoint is required. See --help for more information.")
}
if wireguardPort < 1 || wireguardPort > 65535 {
return xerrors.New("wireguard-port is required and must be between 1 and 65535. See --help for more information.")
}
if wireguardKey == "" {
if wireguardKey == "" && wireguardKeyFile == "" {
return xerrors.New("wireguard-key is required. See --help for more information.")
}
if wireguardKey != "" && wireguardKeyFile != "" {
return xerrors.New("wireguard-key and wireguard-key-file are mutually exclusive. See --help for more information.")
}

logger := slog.Make(sloghuman.Sink(os.Stderr)).Leveled(slog.LevelInfo)
if verbose {
Expand Down Expand Up @@ -182,10 +192,6 @@ func runApp(ctx *cli.Context) error {
if err != nil {
return xerrors.Errorf("could not parse base-url %q: %w", baseURL, err)
}
wireguardKeyParsed, err := tunnelsdk.ParsePrivateKey(wireguardKey)
if err != nil {
return xerrors.Errorf("could not parse wireguard-key %q: %w", wireguardKey, err)
}
wireguardServerIPParsed, err := netip.ParseAddr(wireguardServerIP)
if err != nil {
return xerrors.Errorf("could not parse wireguard-server-ip %q: %w", wireguardServerIP, err)
Expand All @@ -195,6 +201,37 @@ func runApp(ctx *cli.Context) error {
return xerrors.Errorf("could not parse wireguard-network-prefix %q: %w", wireguardNetworkPrefix, err)
}

if wireguardKeyFile != "" {
_, err = os.Stat(wireguardKeyFile)
if xerrors.Is(err, os.ErrNotExist) {
logger.Info(ctx.Context, "generating private key to file", slog.F("path", wireguardKeyFile))
key, err := tunnelsdk.GeneratePrivateKey()
if err != nil {
return xerrors.Errorf("could not generate private key: %w", err)
}

err = os.WriteFile(wireguardKeyFile, []byte(key.String()), 0600)
if err != nil {
return xerrors.Errorf("could not write base64-encoded private key to %q: %w", wireguardKeyFile, err)
}
} else if err != nil {
return xerrors.Errorf("could not stat wireguard-key-file %q: %w", wireguardKeyFile, err)
}

logger.Info(ctx.Context, "reading private key from file", slog.F("path", wireguardKeyFile))
wireguardKeyBytes, err := os.ReadFile(wireguardKeyFile)
if err != nil {
return xerrors.Errorf("could not read wireguard-key-file %q: %w", wireguardKeyFile, err)
}
wireguardKey = string(wireguardKeyBytes)
}

wireguardKeyParsed, err := tunnelsdk.ParsePrivateKey(wireguardKey)
if err != nil {
return xerrors.Errorf("could not parse wireguard-key %q: %w", wireguardKey, err)
}
logger.Info(ctx.Context, "parsed private key", slog.F("hash", wireguardKeyParsed.Hash()))

options := &tunneld.Options{
BaseURL: baseURLParsed,
WireguardEndpoint: wireguardEndpoint,
Expand Down
7 changes: 7 additions & 0 deletions tunnelsdk/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tunnelsdk

import (
"context"
"crypto/sha512"
"encoding/hex"
"fmt"
"net"
Expand Down Expand Up @@ -121,6 +122,12 @@ func (k Key) HexString() string {
return hex.EncodeToString(k.k[:])
}

// Hash returns the SHA512 hash of the key.
func (k Key) Hash() string {
hash := sha512.Sum512(k.k[:])
return hex.EncodeToString(hash[:])
}

// NoisePrivateKey returns the device.NoisePrivateKey for the key. If the key is
// not a private key, an error is returned.
func (k Key) NoisePrivateKey() (device.NoisePrivateKey, error) {
Expand Down

0 comments on commit 16be491

Please sign in to comment.