Skip to content

Commit 5a24e7e

Browse files
authored
Add dns rewrite functionality (#9)
1 parent 233fcfb commit 5a24e7e

File tree

5 files changed

+135
-4
lines changed

5 files changed

+135
-4
lines changed

cmd/localstack/awsutil.go

+17
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,23 @@ func resetListener(changeChannel <-chan bool, server *CustomInteropServer) {
213213

214214
}
215215

216+
func RunDNSRewriter(opts *LsOpts, ctx context.Context) {
217+
if opts.EnableDnsServer != "1" {
218+
log.Debugln("Dns server disabled")
219+
return
220+
}
221+
dnsForwarder, err := NewDnsForwarder(opts.LocalstackIP)
222+
if err != nil {
223+
log.Errorln("Error creating dns forwarder.")
224+
return
225+
}
226+
defer dnsForwarder.Shutdown()
227+
dnsForwarder.Start()
228+
229+
<-ctx.Done()
230+
log.Debugln("Shutting down dns server")
231+
}
232+
216233
func RunHotReloadingListener(server *CustomInteropServer, targetPaths []string, ctx context.Context) {
217234
if len(targetPaths) == 1 && targetPaths[0] == "" {
218235
log.Debugln("Hot reloading disabled.")

cmd/localstack/dns.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package main
2+
3+
import (
4+
"github.com/miekg/dns"
5+
log "github.com/sirupsen/logrus"
6+
"net"
7+
)
8+
9+
type DNSForwarder struct {
10+
server *dns.Server
11+
}
12+
13+
type DNSRewriteForwardHandler struct {
14+
upstreamServer string
15+
redirectTo string
16+
}
17+
18+
func (D DNSRewriteForwardHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
19+
client := dns.Client{
20+
Net: "udp",
21+
}
22+
response, _, err := client.Exchange(r, D.upstreamServer+":53")
23+
if err != nil {
24+
log.Errorln("Error connecting to upstream: ", err)
25+
return
26+
}
27+
for _, rr := range response.Answer {
28+
switch rr.Header().Rrtype {
29+
case dns.TypeA:
30+
if t, ok := rr.(*dns.A); ok {
31+
if t.A.Equal(net.IPv4(127, 0, 0, 1)) {
32+
log.Debugln("Redirecting answer for ", t.Header().Name, "to ", D.redirectTo)
33+
t.A = net.ParseIP(D.redirectTo)
34+
}
35+
}
36+
}
37+
}
38+
err = w.WriteMsg(response)
39+
if err != nil {
40+
log.Errorln("Error writing response: ", err)
41+
}
42+
}
43+
44+
func NewDnsForwarder(upstreamServer string) (*DNSForwarder, error) {
45+
forwarder := &DNSForwarder{
46+
server: &dns.Server{
47+
Net: "udp",
48+
Handler: DNSRewriteForwardHandler{
49+
upstreamServer: upstreamServer,
50+
redirectTo: upstreamServer,
51+
},
52+
},
53+
}
54+
return forwarder, nil
55+
}
56+
57+
func (c *DNSForwarder) Start() {
58+
go func() {
59+
err := c.server.ListenAndServe()
60+
if err != nil {
61+
log.Errorln("Error starting DNS server: ", err)
62+
}
63+
}()
64+
}
65+
66+
func (c *DNSForwarder) Shutdown() {
67+
err := c.server.Shutdown()
68+
if err != nil {
69+
log.Errorln("Error shutting down DNS server: ", err)
70+
}
71+
}

cmd/localstack/main.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type LsOpts struct {
2121
InitTracingPort string
2222
CodeDownloadUrl string
2323
HotReloadingPaths []string
24+
EnableDnsServer string
25+
LocalstackIP string
2426
}
2527

2628
func GetEnvOrDie(env string) string {
@@ -41,6 +43,8 @@ func InitLsOpts() *LsOpts {
4143
// optional or empty
4244
CodeDownloadUrl: os.Getenv("LOCALSTACK_CODE_ARCHIVE_DOWNLOAD_URL"),
4345
HotReloadingPaths: strings.Split(GetenvWithDefault("LOCALSTACK_HOT_RELOADING_PATHS", ""), ","),
46+
EnableDnsServer: os.Getenv("LOCALSTACK_ENABLE_DNS_SERVER"),
47+
LocalstackIP: os.Getenv("LOCALSTACK_HOSTNAME"),
4448
}
4549
}
4650

@@ -57,6 +61,9 @@ func main() {
5761
log.SetReportCaller(true)
5862
// download code archive if env variable is set
5963
DownloadCodeArchive(lsOpts.CodeDownloadUrl)
64+
// enable dns server
65+
dnsServerContext, stopDnsServer := context.WithCancel(context.Background())
66+
go RunDNSRewriter(lsOpts, dnsServerContext)
6067
// parse CLI args
6168
opts, args := getCLIArgs()
6269
bootstrap, handler := getBootstrap(args, opts)
@@ -65,8 +72,9 @@ func main() {
6572
sandbox := rapidcore.
6673
NewSandboxBuilder(bootstrap).
6774
AddShutdownFunc(func() {
68-
log.Debugln("Closing file watcher")
75+
log.Debugln("Closing contexts")
6976
cancelFileWatcher()
77+
stopDnsServer()
7078
}).
7179
AddShutdownFunc(func() { os.Exit(0) }).
7280
SetExtensionsFlag(true).

go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ require (
99
github.com/go-chi/render v1.0.1
1010
github.com/google/uuid v1.1.2
1111
github.com/jessevdk/go-flags v1.4.0
12+
github.com/miekg/dns v1.1.50
1213
github.com/sirupsen/logrus v1.6.0
1314
github.com/stretchr/testify v1.6.1
14-
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
15+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
1516
golang.org/x/sys v0.1.0
1617
)
1718

@@ -20,6 +21,9 @@ require (
2021
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
2122
github.com/pmezard/go-difflib v1.0.0 // indirect
2223
github.com/stretchr/objx v0.1.0 // indirect
24+
golang.org/x/mod v0.4.2 // indirect
2325
golang.org/x/net v0.1.0 // indirect
26+
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
27+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
2428
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
2529
)

go.sum

+33-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGAR
1818
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
1919
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
2020
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
21+
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
22+
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
2123
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2224
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2325
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
3032
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
3133
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3234
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
35+
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
36+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
37+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
38+
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
39+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
40+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
41+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
42+
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
43+
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
3344
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
3445
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
35-
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
36-
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
46+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
47+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
48+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
49+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
50+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
3751
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
52+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
53+
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
54+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
55+
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
56+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3857
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3958
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
4059
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
60+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
61+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
62+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
63+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
4164
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
65+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
66+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
67+
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
68+
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
69+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
70+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
71+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
72+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4273
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
4374
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4475
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

0 commit comments

Comments
 (0)