Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions cmd/veil-daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os/signal"
"strings"
"time"
"unicode"

"github.com/Amnesic-Systems/veil/internal/config"
"github.com/Amnesic-Systems/veil/internal/enclave/nitro"
Expand All @@ -25,8 +26,9 @@ import (
)

const (
defaultExtPort = 8443
defaultIntPort = 8080
defaultExtPort = 8443
defaultIntPort = 8080
defaultDNSResolver = "1.1.1.1"
)

func parseFlags(out io.Writer, args []string) (*config.Veil, error) {
Expand Down Expand Up @@ -69,10 +71,20 @@ func parseFlags(out io.Writer, args []string) (*config.Veil, error) {
"internal port",
)
resolver := fs.String(
"resolver",
"1.1.1.1",
"dns-resolver",
defaultDNSResolver,
"the DNS resolver used by veil",
)
search := fs.String(
"dns-search",
"",
"comma- or whitespace-separated search domains to add to resolv.conf",
)
ndots := fs.Int(
"dns-ndots",
-1,
"ndots option to add to resolv.conf; omitted unless set",
)
silenceApp := fs.Bool(
"silence-app",
false,
Expand Down Expand Up @@ -116,7 +128,9 @@ func parseFlags(out io.Writer, args []string) (*config.Veil, error) {
ExtPort: *extPort,
FQDN: *fqdn,
IntPort: *intPort,
NDots: optionalInt(ndots),
Resolver: *resolver,
SearchDomains: splitList(*search),
SilenceApp: *silenceApp,
Testing: *testing,
VSOCKPort: uint32(*vsockPort),
Expand All @@ -125,6 +139,19 @@ func parseFlags(out io.Writer, args []string) (*config.Veil, error) {
return cfg, validate.Object(cfg)
}

func optionalInt(v *int) *int {
if *v == -1 { // Assume that the flag is unset if it's the default.
return nil
}
return v
}

func splitList(s string) []string {
return strings.FieldsFunc(s, func(r rune) bool {
return r == ',' || unicode.IsSpace(r)
})
}

func run(ctx context.Context, out io.Writer, args []string) (err error) {
defer errs.Wrap(&err, "failed to run service")

Expand Down
23 changes: 23 additions & 0 deletions cmd/veil-daemon/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,29 @@ func TestHelp(t *testing.T) {
)
}

func TestParseDNSFlags(t *testing.T) {
cfg, err := parseFlags(io.Discard, []string{
"-dns-search", "svc.cluster.local,ec2.internal example.com",
"-dns-ndots", "2",
})
require.NoError(t, err)
require.Equal(t, []string{
"svc.cluster.local",
"ec2.internal",
"example.com",
}, cfg.SearchDomains)
require.NotNil(t, cfg.NDots)
require.Equal(t, 2, *cfg.NDots)
}

func TestParseDefaultDNSFlags(t *testing.T) {
cfg, err := parseFlags(io.Discard, nil)
require.NoError(t, err)
require.Equal(t, defaultDNSResolver, cfg.Resolver)
require.Nil(t, cfg.NDots)
require.Empty(t, cfg.SearchDomains)
}

func TestPages(t *testing.T) {
defer stopSvc(startSvc(t, withFlags()))

Expand Down
52 changes: 46 additions & 6 deletions cmd/veil-proxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/Amnesic-Systems/veil/internal/backoff"
"github.com/Amnesic-Systems/veil/internal/config"
"github.com/Amnesic-Systems/veil/internal/errs"
"github.com/Amnesic-Systems/veil/internal/net/dns"
"github.com/Amnesic-Systems/veil/internal/net/nat"
"github.com/Amnesic-Systems/veil/internal/net/proxy"
"github.com/Amnesic-Systems/veil/internal/net/tun"
Expand All @@ -24,30 +25,40 @@ import (
"github.com/mdlayher/vsock"
)

const hostResolvConf = "/etc/resolv.conf"

func parseFlags(out io.Writer, args []string) (_ *config.VeilProxy, err error) {
defer errs.Wrap(&err, "failed to parse flags")

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

dnsForwarder := fs.Bool(
"dns-forwarder",
false,
`Enable DNS forwarder on the tun interface. Have veil-daemon use this
resolver by passing "-dns-resolver 10.0.0.1". The resolver forwards queries
to the nameservers configured in /etc/resolv.conf.`,
)
profile := fs.Bool(
"profile",
false,
"enable profiling",
"Enable profiling.",
)
vsockPort := fs.Uint(
"vsock-port",
tunnel.DefaultVSOCKPort,
"VSOCK listening port that veil connects to",
"VSOCK listening port that veil connects to.",
)
if err := fs.Parse(args); err != nil {
return nil, err
}

// Build and validate the configuration.
cfg := &config.VeilProxy{
Profile: *profile,
VSOCKPort: uint32(*vsockPort),
DNSForwarder: *dnsForwarder,
Profile: *profile,
VSOCKPort: uint32(*vsockPort),
}
return cfg, validate.Object(cfg)
}
Expand All @@ -62,7 +73,7 @@ func listenVSOCK(port uint32) (_ net.Listener, err error) {
return vsock.ListenContextID(cid, port, nil)
}

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

dns, err := startDNSForwarder(ctx, cfg)
if err != nil {
return fmt.Errorf("failed to start DNS forwarder: %w", err)
}
if dns != nil {
defer func() { _ = dns.Close() }()
log.Printf("Started DNS forwarder at %s.", dns.UDPAddr())
}

var wg sync.WaitGroup
wg.Add(2)
go proxy.VSOCKToTun(vm, tunDev, ch, &wg)
Expand All @@ -112,6 +132,26 @@ func acceptLoop(ctx context.Context, ln net.Listener) {
}
}

func startDNSForwarder(
ctx context.Context,
cfg *config.VeilProxy,
) (*dns.Forwarder, error) {
if !cfg.DNSForwarder {
return nil, nil
}

upstreams, err := dns.UpstreamsFromFile(hostResolvConf)
if err != nil {
return nil, fmt.Errorf("failed to read DNS upstreams from %s: %w",
hostResolvConf, err)
}

return dns.Start(ctx, dns.Config{
ListenAddr: net.JoinHostPort(tun.ProxyIP, "53"),
Upstreams: upstreams,
})
}

func run(ctx context.Context, out io.Writer, args []string) (origErr error) {
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
defer cancel()
Expand Down Expand Up @@ -156,7 +196,7 @@ func run(ctx context.Context, out io.Writer, args []string) (origErr error) {

// Accept new connections from the VSOCK listener and begin forwarding
// packets.
acceptLoop(ctx, ln)
acceptLoop(ctx, ln, cfg)
return nil
}

Expand Down
11 changes: 11 additions & 0 deletions internal/config/veil.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,18 @@ type Veil struct {
// is only used by the enclave application. This field is required.
IntPort int

// NDots contains the ndots resolver option that the enclave should use.
// If nil, veil leaves this option out of resolv.conf.
NDots *int

// Resolver contains the IP address of the DNS resolver that the enclave
// should use, e.g., 1.1.1.1.
Resolver string

// SearchDomains contains the resolver search list that the enclave should
// use.
SearchDomains []string

// SilenceApp can be set to discard the application's stdout and stderr if
// -app-cmd is used.
SilenceApp bool
Expand Down Expand Up @@ -102,6 +110,9 @@ func (c *Veil) Validate() map[string]string {
if c.VSOCKPort == 0 {
problems["-vsock-port"] = "port must not be 0"
}
if c.NDots != nil && (*c.NDots < 0 || *c.NDots > 15) {
problems["-dns-ndots"] = "must be between 0 and 15"
}

// Check invalid field combinations.
if c.SilenceApp && c.AppCmd == "" {
Expand Down
4 changes: 4 additions & 0 deletions internal/config/veil_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package config

// VeilProxy represents veil-proxy's configuration.
type VeilProxy struct {
// DNSForwarder enables a forwarding DNS resolver on the host side of
// veil's TUN interface.
DNSForwarder bool

// Profile can be set to true to enable profiling.
Profile bool

Expand Down
14 changes: 13 additions & 1 deletion internal/config/veil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package config
import (
"testing"

"github.com/Amnesic-Systems/veil/internal/types/validate"
"github.com/stretchr/testify/require"

"github.com/Amnesic-Systems/veil/internal/addr"
"github.com/Amnesic-Systems/veil/internal/types/validate"
)

func TestVeilConfig(t *testing.T) {
Expand Down Expand Up @@ -46,6 +48,16 @@ func TestVeilConfig(t *testing.T) {
VSOCKPort: 1024,
},
},
{
name: "invalid ndots",
cfg: &Veil{
ExtPort: 8443,
IntPort: 8080,
NDots: addr.Of(16),
VSOCKPort: 1024,
},
wantErrs: 1,
},
}

for _, c := range cases {
Expand Down
Loading
Loading