Skip to content

Commit

Permalink
add DNS service on TCP
Browse files Browse the repository at this point in the history
  • Loading branch information
sakai135 committed Apr 10, 2022
1 parent 124ec82 commit 692d0f2
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 6 deletions.
13 changes: 13 additions & 0 deletions cmd/gvproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"flag"
"fmt"
"net"
"os"
"os/signal"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/containers/gvisor-tap-vsock/pkg/virtualnetwork"
"github.com/pkg/errors"
"github.com/sakai135/wsl-vpnkit/pkg/services/dns"
"github.com/sakai135/wsl-vpnkit/pkg/transport"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -123,6 +125,17 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
return err
}

lnDns, err := vn.Listen("tcp", fmt.Sprintf("%s:53", gatewayIP))
if err != nil {
return err
}
go func() {
err := dns.ServeListener(lnDns, configuration.DNS)
if err != nil {
log.Error(err)
}
}()

conn := transport.GetStdioConn()
err = vn.AcceptQemu(ctx, conn)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion distro/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN go-licenses save ./cmd/gvproxy --save_path ./licenses/gvproxy && \
go-licenses save ./cmd/vm --save_path ./licenses/vm

FROM alpine:3.15.4
RUN apk add --no-cache openrc iptables && \
RUN apk add --no-cache openrc iptables bind-tools && \
apk list --installed
ARG REF=https://example.com/
ARG VERSION=v0.0.0
Expand Down
112 changes: 112 additions & 0 deletions pkg/services/dns/dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package dns

import (
"context"
"fmt"
"net"
"strings"

"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/miekg/dns"
log "github.com/sirupsen/logrus"
)

type dnsHandler struct {
zones []types.Zone
}

func (h *dnsHandler) handle(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.RecursionAvailable = true
h.addAnswers(m)
if err := w.WriteMsg(m); err != nil {
log.Error(err)
}
}

func (h *dnsHandler) addAnswers(m *dns.Msg) {
for _, q := range m.Question {
for _, zone := range h.zones {
zoneSuffix := fmt.Sprintf(".%s", zone.Name)
if strings.HasSuffix(q.Name, zoneSuffix) {
if q.Qtype != dns.TypeA {
return
}
for _, record := range zone.Records {
withoutZone := strings.TrimSuffix(q.Name, zoneSuffix)
if (record.Name != "" && record.Name == withoutZone) ||
(record.Regexp != nil && record.Regexp.MatchString(withoutZone)) {
m.Answer = append(m.Answer, &dns.A{
Hdr: dns.RR_Header{
Name: q.Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 0,
},
A: record.IP,
})
return
}
}
if !zone.DefaultIP.Equal(net.IP("")) {
m.Answer = append(m.Answer, &dns.A{
Hdr: dns.RR_Header{
Name: q.Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 0,
},
A: zone.DefaultIP,
})
return
}
m.Rcode = dns.RcodeNameError
return
}
}

resolver := net.Resolver{
PreferGo: false,
}
switch q.Qtype {
case dns.TypeNS:
records, err := resolver.LookupNS(context.TODO(), q.Name)
if err != nil {
m.Rcode = dns.RcodeNameError
return
}
for _, ns := range records {
m.Answer = append(m.Answer, &dns.NS{
Hdr: dns.RR_Header{
Name: q.Name,
Rrtype: dns.TypeNS,
Class: dns.ClassINET,
Ttl: 0,
},
Ns: ns.Host,
})
}
case dns.TypeA:
ips, err := resolver.LookupIPAddr(context.TODO(), q.Name)
if err != nil {
m.Rcode = dns.RcodeNameError
return
}
for _, ip := range ips {
if len(ip.IP.To4()) != net.IPv4len {
continue
}
m.Answer = append(m.Answer, &dns.A{
Hdr: dns.RR_Header{
Name: q.Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 0,
},
A: ip.IP.To4(),
})
}
}
}
}
19 changes: 19 additions & 0 deletions pkg/services/dns/tcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dns

import (
"net"

"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/miekg/dns"
)

func ServeListener(ln net.Listener, zones []types.Zone) error {
mux := dns.NewServeMux()
handler := &dnsHandler{zones: zones}
mux.HandleFunc(".", handler.handle)
srv := &dns.Server{
Listener: ln,
Handler: mux,
}
return srv.ActivateAndServe()
}
11 changes: 6 additions & 5 deletions wsl-vpnkit
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ check_ping () {

check_dns () {
TYPE=$([ "$1" = "4" ] && echo 'A' || echo 'AAAA')
nslookup -type=$TYPE $2 $3 >/dev/null && \
echo "check: ✔️ nslookup success for $2 $TYPE using $3" || \
echo "check: ❌ nslookup fail for $2 $TYPE using $3"
PROTOCOL=$([ "$4" = "tcp" ] && echo 'tcp' || echo 'notcp')
dig $TYPE $2 @$3 +$PROTOCOL +timeout=1 >/dev/null && \
echo "check: ✔️ dig success for $2 $TYPE $PROTOCOL using $3" || \
echo "check: ❌ dig fail for $2 $TYPE $PROTOCOL using $3"
}

check_https () {
Expand All @@ -130,10 +131,10 @@ check () {
check_dns 4 $CHECK_HOST $VPNKIT_GATEWAY_IP
check_dns 4 $CHECK_HOST $WSL2_GATEWAY_IP
check_dns 4 $CHECK_HOST $CHECK_DNS
check_dns 4 $CHECK_HOST $DNS_IP tcp
check_dns 4 $CHECK_HOST $CHECK_DNS tcp
check_ping 4 'external host' $CHECK_HOST
check_dns 6 $CHECK_HOST $DNS_IP
check_dns 6 $CHECK_HOST $VPNKIT_GATEWAY_IP
check_dns 6 $CHECK_HOST $WSL2_GATEWAY_IP
check_dns 6 $CHECK_HOST $CHECK_DNS
check_ping 6 'external host' $CHECK_HOST
check_https "https://$CHECK_HOST"
Expand Down

0 comments on commit 692d0f2

Please sign in to comment.