Server -privkey option and client -pubkey option.

This commit is contained in:
David Fifield
2020-04-18 17:35:32 -06:00
parent 7dc344713c
commit 505db3ec23
3 changed files with 112 additions and 31 deletions
+33 -10
View File
@@ -222,39 +222,62 @@ func run(pubkey []byte, domain dns.Name, localAddr *net.TCPAddr, remoteAddr net.
func main() {
var dohURL string
var dotAddr string
var pubkeyFilename string
var pubkeyString string
var udpAddr string
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [-doh URL|-dot ADDR|-udp ADDR] PUBKEY DOMAIN LOCALADDR\n", os.Args[0])
fmt.Fprintf(flag.CommandLine.Output(), `Usage:
%[1]s [-doh URL|-dot ADDR|-udp ADDR] -pubkey PUBKEY DOMAIN LOCALADDR
Examples:
%[1]s -doh https://resolver.example/dns-query -pubkey 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff t.example.com 127.0.0.1:7000
%[1]s -dot resolver.example:853 -pubkey 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff t.example.com 127.0.0.1:7000
`, os.Args[0])
flag.PrintDefaults()
}
flag.StringVar(&dohURL, "doh", "", "URL of DoH resolver")
flag.StringVar(&dotAddr, "dot", "", "address of DoT resolver")
flag.StringVar(&pubkeyString, "pubkey", "", fmt.Sprintf("server public key (%d hex digits)", hex.EncodedLen(noise.KeyLen)))
flag.StringVar(&pubkeyString, "pubkey-file", "", "read server public key from file")
flag.StringVar(&udpAddr, "udp", "", "address of UDP DNS resolver")
flag.Parse()
log.SetFlags(log.LstdFlags | log.LUTC)
if flag.NArg() != 3 {
if flag.NArg() != 2 {
flag.Usage()
os.Exit(1)
}
pubkey, err := hex.DecodeString(flag.Arg(0))
domain, err := dns.ParseName(flag.Arg(0))
if err != nil {
fmt.Fprintf(os.Stderr, "invalid pubkey %+q: %v\n", flag.Arg(0), err)
fmt.Fprintf(os.Stderr, "invalid domain %+q: %v\n", flag.Arg(0), err)
os.Exit(1)
}
domain, err := dns.ParseName(flag.Arg(1))
if err != nil {
fmt.Fprintf(os.Stderr, "invalid domain %+q: %v\n", flag.Arg(1), err)
os.Exit(1)
}
localAddr, err := net.ResolveTCPAddr("tcp", flag.Arg(2))
localAddr, err := net.ResolveTCPAddr("tcp", flag.Arg(1))
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
var pubkey []byte
if pubkeyString != "" {
var err error
pubkey, err = hex.DecodeString(pubkeyString)
if err == nil && len(pubkey) != noise.KeyLen {
err = fmt.Errorf("length is %d, expected %d", len(pubkey), noise.KeyLen)
}
if err != nil {
fmt.Fprintf(os.Stderr, "pubkey format error: %v\n", err)
os.Exit(1)
}
}
if len(pubkey) == 0 {
fmt.Fprintf(os.Stderr, "the -pubkey option is required\n")
os.Exit(1)
}
// Iterate over the remote resolver address options and select one and
// only one.
var remoteAddr net.Addr
+76 -21
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/base32"
"encoding/binary"
"encoding/hex"
"flag"
"fmt"
"io"
@@ -490,13 +491,18 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
return nil
}
func run(domain dns.Name, upstream net.Addr, udpAddr string) error {
func generateKeypair() error {
privkey, pubkey, err := noise.GenerateKeypair()
if err != nil {
return err
}
log.Printf("privkey %x", privkey)
log.Printf(" pubkey %x", pubkey)
fmt.Printf("privkey: %x\n", privkey)
fmt.Printf("pubkey: %x\n", pubkey)
return nil
}
func run(privkey, pubkey []byte, domain dns.Name, upstream net.Addr, udpAddr string) error {
log.Printf("pubkey %x", pubkey)
// Start up the virtual PacketConn for turbotunnel.
ttConn := turbotunnel.NewQueuePacketConn(turbotunnel.DummyAddr{}, idleTimeout*2)
@@ -535,34 +541,83 @@ func run(domain dns.Name, upstream net.Addr, udpAddr string) error {
}
func main() {
var genKey bool
var privkeyString string
var udpAddr string
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s -udp ADDR DOMAIN UPSTREAMADDR\n", os.Args[0])
fmt.Fprintf(flag.CommandLine.Output(), `Usage:
%[1]s -gen-key
%[1]s -udp ADDR -privkey PRIVKEY DOMAIN UPSTREAMADDR
Example:
%[1]s -gen-key
%[1]s -udp 127.0.0.1:5300 -privkey 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef server.key t.example.com 127.0.0.1:8000
`, os.Args[0])
flag.PrintDefaults()
}
flag.BoolVar(&genKey, "gen-key", false, "generate a server keypair; print to stdout")
flag.StringVar(&privkeyString, "privkey", "", fmt.Sprintf("server private key (%d hex digits)", hex.EncodedLen(noise.KeyLen)))
flag.StringVar(&udpAddr, "udp", "", "UDP address to listen on (required)")
flag.Parse()
log.SetFlags(log.LstdFlags | log.LUTC)
if flag.NArg() != 2 {
flag.Usage()
os.Exit(1)
}
domain, err := dns.ParseName(flag.Arg(0))
if err != nil {
fmt.Fprintf(os.Stderr, "invalid domain %+q: %v\n", flag.Arg(0), err)
os.Exit(1)
}
upstream, err := net.ResolveTCPAddr("tcp", flag.Arg(1))
if err != nil {
fmt.Fprintf(os.Stderr, "cannot resolve %+q: %v\n", flag.Arg(1), err)
os.Exit(1)
}
if genKey {
// -gen-key mode.
if flag.NArg() != 0 || privkeyString != "" || udpAddr != "" {
flag.Usage()
os.Exit(1)
}
if err := generateKeypair(); err != nil {
fmt.Fprintf(os.Stderr, "cannot generate keypair: %v\n", err)
os.Exit(1)
}
} else {
// Ordinary server mode.
if flag.NArg() != 2 {
flag.Usage()
os.Exit(1)
}
domain, err := dns.ParseName(flag.Arg(0))
if err != nil {
fmt.Fprintf(os.Stderr, "invalid domain %+q: %v\n", flag.Arg(0), err)
os.Exit(1)
}
upstream, err := net.ResolveTCPAddr("tcp", flag.Arg(1))
if err != nil {
fmt.Fprintf(os.Stderr, "cannot resolve %+q: %v\n", flag.Arg(1), err)
os.Exit(1)
}
err = run(domain, upstream, udpAddr)
if err != nil {
log.Fatal(err)
var privkey []byte
if privkeyString != "" {
var err error
privkey, err = hex.DecodeString(privkeyString)
if err == nil && len(privkey) != noise.KeyLen {
err = fmt.Errorf("length is %d, expected %d", len(privkey), noise.KeyLen)
}
if err != nil {
fmt.Fprintf(os.Stderr, "privkey format error: %v\n", err)
os.Exit(1)
}
}
if len(privkey) == 0 {
log.Println("generating a temporary one-time keypair")
log.Println("use the -privkey option for a persistent server keypair")
var err error
privkey, _, err = noise.GenerateKeypair()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
pubkey := noise.PubkeyFromPrivkey(privkey)
err = run(privkey, pubkey, domain, upstream, udpAddr)
if err != nil {
log.Fatal(err)
}
}
}
+3
View File
@@ -11,6 +11,9 @@ import (
"github.com/flynn/noise"
)
// The length of public and private keys as returned by GenerateKeypair.
const KeyLen = 32
func readMessage(r io.Reader) ([]byte, error) {
var length uint16
err := binary.Read(r, binary.BigEndian, &length)