Skip to content

Commit a4d7cb6

Browse files
Add DNS forwarder to veil-proxy.
Users currently have little flexibility in how their enclave uses DNS: veil-daemon's -resolver flag is all there is. Users however may also want to configure search domains, or have the enclave's DNS handled like the EC2 host's. To make all of that possible, this PR introduces a new command line flag to veil-proxy: -dns-forwarder. When enabled, it instructs veil-proxy to open both a UDP and TCP listener on port 53 on the tun interface. All incoming payload (the forwarder has no understanding of DNS; it simply shuffles around bytes) is then blindly forwarded to the EC2 host's nameservers configured in /etc/resolv.conf. To make use of this feature, start veil-proxy with the new flag: veil-proxy -dns-forwarder Then, set veil-daemon's resolver to the host's IP address: veil-daemon -resolver 10.0.0.1 Fixes #61.
1 parent 983775b commit a4d7cb6

7 files changed

Lines changed: 522 additions & 11 deletions

File tree

cmd/veil-proxy/main.go

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/Amnesic-Systems/veil/internal/backoff"
1717
"github.com/Amnesic-Systems/veil/internal/config"
1818
"github.com/Amnesic-Systems/veil/internal/errs"
19+
"github.com/Amnesic-Systems/veil/internal/net/dns"
1920
"github.com/Amnesic-Systems/veil/internal/net/nat"
2021
"github.com/Amnesic-Systems/veil/internal/net/proxy"
2122
"github.com/Amnesic-Systems/veil/internal/net/tun"
@@ -24,30 +25,40 @@ import (
2425
"github.com/mdlayher/vsock"
2526
)
2627

28+
const hostResolvConf = "/etc/resolv.conf"
29+
2730
func parseFlags(out io.Writer, args []string) (_ *config.VeilProxy, err error) {
2831
defer errs.Wrap(&err, "failed to parse flags")
2932

3033
fs := flag.NewFlagSet("veil-proxy", flag.ContinueOnError)
3134
fs.SetOutput(out)
3235

36+
dnsForwarder := fs.Bool(
37+
"dns-forwarder",
38+
false,
39+
`Enable DNS forwarder on the tun interface. Have veil-daemon use this
40+
resolver by passing "-resolver 10.0.0.1". The resolver forwards queries
41+
to the nameservers configured in /etc/resolv.conf.`,
42+
)
3343
profile := fs.Bool(
3444
"profile",
3545
false,
36-
"enable profiling",
46+
"Enable profiling.",
3747
)
3848
vsockPort := fs.Uint(
3949
"vsock-port",
4050
tunnel.DefaultVSOCKPort,
41-
"VSOCK listening port that veil connects to",
51+
"VSOCK listening port that veil connects to.",
4252
)
4353
if err := fs.Parse(args); err != nil {
4454
return nil, err
4555
}
4656

4757
// Build and validate the configuration.
4858
cfg := &config.VeilProxy{
49-
Profile: *profile,
50-
VSOCKPort: uint32(*vsockPort),
59+
DNSForwarder: *dnsForwarder,
60+
Profile: *profile,
61+
VSOCKPort: uint32(*vsockPort),
5162
}
5263
return cfg, validate.Object(cfg)
5364
}
@@ -62,7 +73,7 @@ func listenVSOCK(port uint32) (_ net.Listener, err error) {
6273
return vsock.ListenContextID(cid, port, nil)
6374
}
6475

65-
func acceptLoop(ctx context.Context, ln net.Listener) {
76+
func acceptLoop(ctx context.Context, ln net.Listener, cfg *config.VeilProxy) {
6677
// Print errors that occur while forwarding packets.
6778
ch := make(chan error)
6879
defer close(ch)
@@ -93,6 +104,15 @@ func acceptLoop(ctx context.Context, ln net.Listener) {
93104
defer func() { _ = tunDev.Close() }()
94105
log.Print("Created tun device.")
95106

107+
dns, err := startDNSForwarder(ctx, cfg)
108+
if err != nil {
109+
return fmt.Errorf("failed to start DNS forwarder: %w", err)
110+
}
111+
if dns != nil {
112+
defer func() { _ = dns.Close() }()
113+
log.Printf("Started DNS forwarder at %s.", dns.UDPAddr())
114+
}
115+
96116
var wg sync.WaitGroup
97117
wg.Add(2)
98118
go proxy.VSOCKToTun(vm, tunDev, ch, &wg)
@@ -112,6 +132,26 @@ func acceptLoop(ctx context.Context, ln net.Listener) {
112132
}
113133
}
114134

135+
func startDNSForwarder(
136+
ctx context.Context,
137+
cfg *config.VeilProxy,
138+
) (*dns.Forwarder, error) {
139+
if !cfg.DNSForwarder {
140+
return nil, nil
141+
}
142+
143+
upstreams, err := dns.UpstreamsFromFile(hostResolvConf)
144+
if err != nil {
145+
return nil, fmt.Errorf("failed to read DNS upstreams from %s: %w",
146+
hostResolvConf, err)
147+
}
148+
149+
return dns.Start(ctx, dns.Config{
150+
ListenAddr: net.JoinHostPort(tun.ProxyIP, "53"),
151+
Upstreams: upstreams,
152+
})
153+
}
154+
115155
func run(ctx context.Context, out io.Writer, args []string) (origErr error) {
116156
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
117157
defer cancel()
@@ -156,7 +196,7 @@ func run(ctx context.Context, out io.Writer, args []string) (origErr error) {
156196

157197
// Accept new connections from the VSOCK listener and begin forwarding
158198
// packets.
159-
acceptLoop(ctx, ln)
199+
acceptLoop(ctx, ln, cfg)
160200
return nil
161201
}
162202

internal/config/veil_proxy.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package config
22

33
// VeilProxy represents veil-proxy's configuration.
44
type VeilProxy struct {
5+
// DNSForwarder enables a forwarding DNS resolver on the host side of
6+
// veil's TUN interface.
7+
DNSForwarder bool
8+
59
// Profile can be set to true to enable profiling.
610
Profile bool
711

0 commit comments

Comments
 (0)