From 80f3c2a740284a3080151e4e30cf131848f1128e Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Fri, 13 Jan 2023 14:34:47 +0100 Subject: [PATCH 1/3] add dns rewrite functionality --- cmd/localstack/awsutil.go | 16 +++++++++ cmd/localstack/dns.go | 70 +++++++++++++++++++++++++++++++++++++++ cmd/localstack/main.go | 8 +++++ go.mod | 6 +++- go.sum | 35 ++++++++++++++++++-- 5 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 cmd/localstack/dns.go diff --git a/cmd/localstack/awsutil.go b/cmd/localstack/awsutil.go index 5fcdc2a..d507d5e 100644 --- a/cmd/localstack/awsutil.go +++ b/cmd/localstack/awsutil.go @@ -213,6 +213,22 @@ func resetListener(changeChannel <-chan bool, server *CustomInteropServer) { } +func RunDNSRewriter(opts *LsOpts, ctx context.Context) { + if opts.EnableDnsServer != "1" { + log.Debugln("Dns server disabled") + return + } + dnsForwarder, err := NewDnsForwarder(opts.LocalstackIP) + if err != nil { + log.Errorln("Error creating dns forwarder.") + } + defer dnsForwarder.Shutdown() + dnsForwarder.Start() + + <-ctx.Done() + log.Debugln("Shutting down dns server") +} + func RunHotReloadingListener(server *CustomInteropServer, targetPaths []string, ctx context.Context) { if len(targetPaths) == 1 && targetPaths[0] == "" { log.Debugln("Hot reloading disabled.") diff --git a/cmd/localstack/dns.go b/cmd/localstack/dns.go new file mode 100644 index 0000000..1927554 --- /dev/null +++ b/cmd/localstack/dns.go @@ -0,0 +1,70 @@ +package main + +import ( + "github.com/miekg/dns" + log "github.com/sirupsen/logrus" + "net" +) + +type DNSForwarder struct { + server *dns.Server +} + +type DNSRewriteForwardHandler struct { + upstreamServer string + redirectTo string +} + +func (D DNSRewriteForwardHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { + client := dns.Client{ + Net: "udp", + } + response, _, err := client.Exchange(r, D.upstreamServer+":53") + if err != nil { + log.Errorln("Error connecting to upstream: ", err) + } + for _, rr := range response.Answer { + switch rr.Header().Rrtype { + case dns.TypeA: + if t, ok := rr.(*dns.A); ok { + if t.A.Equal(net.IPv4(127, 0, 0, 1)) { + log.Debugln("Redirecting answer for ", t.Header().Name, "to ", D.redirectTo) + t.A = net.ParseIP(D.redirectTo) + } + } + } + } + err = w.WriteMsg(response) + if err != nil { + log.Errorln("Error writing response: ", err) + } +} + +func NewDnsForwarder(upstreamServer string) (*DNSForwarder, error) { + forwarder := &DNSForwarder{ + server: &dns.Server{ + Net: "udp", + Handler: DNSRewriteForwardHandler{ + upstreamServer: upstreamServer, + redirectTo: upstreamServer, + }, + }, + } + return forwarder, nil +} + +func (c *DNSForwarder) Start() { + go func() { + err := c.server.ListenAndServe() + if err != nil { + log.Errorln("Error starting DNS server: ", err) + } + }() +} + +func (c *DNSForwarder) Shutdown() { + err := c.server.Shutdown() + if err != nil { + log.Errorln("Error shutting down DNS server: ", err) + } +} diff --git a/cmd/localstack/main.go b/cmd/localstack/main.go index 3f44870..cb5a413 100644 --- a/cmd/localstack/main.go +++ b/cmd/localstack/main.go @@ -21,6 +21,8 @@ type LsOpts struct { InitTracingPort string CodeDownloadUrl string HotReloadingPaths []string + EnableDnsServer string + LocalstackIP string } func GetEnvOrDie(env string) string { @@ -41,6 +43,8 @@ func InitLsOpts() *LsOpts { // optional or empty CodeDownloadUrl: os.Getenv("LOCALSTACK_CODE_ARCHIVE_DOWNLOAD_URL"), HotReloadingPaths: strings.Split(GetenvWithDefault("LOCALSTACK_HOT_RELOADING_PATHS", ""), ","), + EnableDnsServer: os.Getenv("LOCALSTACK_ENABLE_DNS_SERVER"), + LocalstackIP: os.Getenv("LOCALSTACK_HOSTNAME"), } } @@ -57,6 +61,9 @@ func main() { log.SetReportCaller(true) // download code archive if env variable is set DownloadCodeArchive(lsOpts.CodeDownloadUrl) + // enable dns server + dnsServerContext, stopDnsServer := context.WithCancel(context.Background()) + go RunDNSRewriter(lsOpts, dnsServerContext) // parse CLI args opts, args := getCLIArgs() bootstrap, handler := getBootstrap(args, opts) @@ -67,6 +74,7 @@ func main() { AddShutdownFunc(func() { log.Debugln("Closing file watcher") cancelFileWatcher() + stopDnsServer() }). AddShutdownFunc(func() { os.Exit(0) }). SetExtensionsFlag(true). diff --git a/go.mod b/go.mod index 7e17c86..68fda7f 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,10 @@ require ( github.com/go-chi/render v1.0.1 github.com/google/uuid v1.1.2 github.com/jessevdk/go-flags v1.4.0 + github.com/miekg/dns v1.1.50 github.com/sirupsen/logrus v1.6.0 github.com/stretchr/testify v1.6.1 - golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.1.0 ) @@ -20,6 +21,9 @@ require ( github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.1.0 // indirect + golang.org/x/mod v0.4.2 // indirect golang.org/x/net v0.1.0 // indirect + golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/go.sum b/go.sum index 576d027..8d30ee9 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGAR github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -30,15 +32,44 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From e805474b1e37e8f9ec4d3868d302e9cc2c1429ef Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Fri, 13 Jan 2023 15:26:11 +0100 Subject: [PATCH 2/3] some changes --- cmd/localstack/dns.go | 1 + cmd/localstack/main.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/localstack/dns.go b/cmd/localstack/dns.go index 1927554..fc68819 100644 --- a/cmd/localstack/dns.go +++ b/cmd/localstack/dns.go @@ -22,6 +22,7 @@ func (D DNSRewriteForwardHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { response, _, err := client.Exchange(r, D.upstreamServer+":53") if err != nil { log.Errorln("Error connecting to upstream: ", err) + return } for _, rr := range response.Answer { switch rr.Header().Rrtype { diff --git a/cmd/localstack/main.go b/cmd/localstack/main.go index cb5a413..ec27a91 100644 --- a/cmd/localstack/main.go +++ b/cmd/localstack/main.go @@ -72,7 +72,7 @@ func main() { sandbox := rapidcore. NewSandboxBuilder(bootstrap). AddShutdownFunc(func() { - log.Debugln("Closing file watcher") + log.Debugln("Closing contexts") cancelFileWatcher() stopDnsServer() }). From 28e9c0b296e7ccb77436eacaffc3b91a99d5d39d Mon Sep 17 00:00:00 2001 From: Daniel Fangl Date: Mon, 16 Jan 2023 12:11:52 +0100 Subject: [PATCH 3/3] add missing return --- cmd/localstack/awsutil.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/localstack/awsutil.go b/cmd/localstack/awsutil.go index d507d5e..96e1947 100644 --- a/cmd/localstack/awsutil.go +++ b/cmd/localstack/awsutil.go @@ -221,6 +221,7 @@ func RunDNSRewriter(opts *LsOpts, ctx context.Context) { dnsForwarder, err := NewDnsForwarder(opts.LocalstackIP) if err != nil { log.Errorln("Error creating dns forwarder.") + return } defer dnsForwarder.Shutdown() dnsForwarder.Start()