2021-03-08 16:46:23 +00:00
|
|
|
package proxydns
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
|
|
|
"github.com/cloudflare/cloudflared/logger"
|
|
|
|
"github.com/cloudflare/cloudflared/metrics"
|
|
|
|
"github.com/cloudflare/cloudflared/tunneldns"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Command(hidden bool) *cli.Command {
|
|
|
|
return &cli.Command{
|
|
|
|
Name: "proxy-dns",
|
2021-03-16 22:36:46 +00:00
|
|
|
Action: cliutil.ConfiguredAction(Run),
|
2021-02-05 01:44:03 +00:00
|
|
|
|
2021-03-16 22:36:46 +00:00
|
|
|
Usage: "Run a DNS over HTTPS proxy server.",
|
2021-03-08 16:46:23 +00:00
|
|
|
Flags: []cli.Flag{
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "metrics",
|
|
|
|
Value: "localhost:",
|
|
|
|
Usage: "Listen address for metrics reporting.",
|
|
|
|
EnvVars: []string{"TUNNEL_METRICS"},
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "address",
|
|
|
|
Usage: "Listen address for the DNS over HTTPS proxy server.",
|
|
|
|
Value: "localhost",
|
|
|
|
EnvVars: []string{"TUNNEL_DNS_ADDRESS"},
|
|
|
|
},
|
|
|
|
// Note TUN-3758 , we use Int because UInt is not supported with altsrc
|
|
|
|
&cli.IntFlag{
|
|
|
|
Name: "port",
|
|
|
|
Usage: "Listen on given port for the DNS over HTTPS proxy server.",
|
|
|
|
Value: 53,
|
|
|
|
EnvVars: []string{"TUNNEL_DNS_PORT"},
|
|
|
|
},
|
|
|
|
&cli.StringSliceFlag{
|
|
|
|
Name: "upstream",
|
|
|
|
Usage: "Upstream endpoint URL, you can specify multiple endpoints for redundancy.",
|
|
|
|
Value: cli.NewStringSlice("https://1.1.1.1/dns-query", "https://1.0.0.1/dns-query"),
|
|
|
|
EnvVars: []string{"TUNNEL_DNS_UPSTREAM"},
|
|
|
|
},
|
|
|
|
&cli.StringSliceFlag{
|
|
|
|
Name: "bootstrap",
|
|
|
|
Usage: "bootstrap endpoint URL, you can specify multiple endpoints for redundancy.",
|
|
|
|
Value: cli.NewStringSlice("https://162.159.36.1/dns-query", "https://162.159.46.1/dns-query", "https://[2606:4700:4700::1111]/dns-query", "https://[2606:4700:4700::1001]/dns-query"),
|
|
|
|
EnvVars: []string{"TUNNEL_DNS_BOOTSTRAP"},
|
|
|
|
},
|
|
|
|
&cli.IntFlag{
|
|
|
|
Name: "max-upstream-conns",
|
|
|
|
Usage: "Maximum concurrent connections to upstream. Setting to 0 means unlimited.",
|
|
|
|
Value: tunneldns.MaxUpstreamConnsDefault,
|
|
|
|
EnvVars: []string{"TUNNEL_DNS_MAX_UPSTREAM_CONNS"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ArgsUsage: " ", // can't be the empty string or we get the default output
|
|
|
|
Hidden: hidden,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run implements a foreground runner
|
|
|
|
func Run(c *cli.Context) error {
|
|
|
|
log := logger.CreateLoggerFromContext(c, logger.EnableTerminalLog)
|
|
|
|
|
|
|
|
metricsListener, err := net.Listen("tcp", c.String("metrics"))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal().Err(err).Msg("Failed to open the metrics listener")
|
|
|
|
}
|
|
|
|
|
|
|
|
go metrics.ServeMetrics(metricsListener, nil, nil, log)
|
|
|
|
|
|
|
|
listener, err := tunneldns.CreateListener(
|
|
|
|
c.String("address"),
|
|
|
|
// Note TUN-3758 , we use Int because UInt is not supported with altsrc
|
|
|
|
uint16(c.Int("port")),
|
|
|
|
c.StringSlice("upstream"),
|
|
|
|
c.StringSlice("bootstrap"),
|
|
|
|
c.Int("max-upstream-conns"),
|
|
|
|
log,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Err(err).Msg("Failed to create the listeners")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to start the server
|
|
|
|
readySignal := make(chan struct{})
|
|
|
|
err = listener.Start(readySignal)
|
|
|
|
if err != nil {
|
|
|
|
log.Err(err).Msg("Failed to start the listeners")
|
|
|
|
return listener.Stop()
|
|
|
|
}
|
|
|
|
<-readySignal
|
|
|
|
|
|
|
|
// Wait for signal
|
|
|
|
signals := make(chan os.Signal, 10)
|
|
|
|
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
defer signal.Stop(signals)
|
|
|
|
<-signals
|
|
|
|
|
|
|
|
// Shut down server
|
|
|
|
err = listener.Stop()
|
|
|
|
if err != nil {
|
|
|
|
log.Err(err).Msg("failed to stop")
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|