Skip to content

Commit

Permalink
Add basic DNS and DNS-over-TLS implementation
Browse files Browse the repository at this point in the history
- add random and incremental DNS fallback strategy
- add option to handle DNS requests based on regex patterns
- made Makefiles plugin independent
- extended config
- set default plugins directory in Dockerfile
  • Loading branch information
prskr committed Apr 1, 2020
1 parent 0ed9070 commit 63ba6da
Show file tree
Hide file tree
Showing 15 changed files with 546 additions and 27 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ RUN make CONTAINER=yes

FROM scratch

ENV INETMOCK_PLUGINS_DIRECTORY=/app/plugins/

WORKDIR /app

COPY --from=build /etc/passwd /etc/group /etc/
Expand Down
36 changes: 35 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,38 @@ endpoints:
certCachePath: /tmp/inetmock/
target:
ipAddress: 127.0.0.1
port: 80
port: 80
plainDns:
handler: dns_mock
listenAddress: 0.0.0.0
port: 53
options:
fallback:
strategy: incremental
args:
startIP: 10.0.0.0
rules:
- pattern: ".*\\.google\\.com"
response: 1.1.1.1
- pattern: ".*\\.reddit\\.com"
response: 2.2.2.2
dnsOverTlsDowngrade:
handler: tls_interceptor
listenAddress: 0.0.0.0
port: 853
options:
ecdsaCurve: P256
validity:
ca:
notBeforeRelative: 17520h
notAfterRelative: 17520h
domain:
notBeforeRelative: 168h
notAfterRelative: 168h
rootCaCert:
publicKey: ./ca.pem
privateKey: ./ca.key
certCachePath: /tmp/inetmock/
target:
ipAddress: 127.0.0.1
port: 53
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ module github.com/baez90/inetmock
go 1.13

require (
github.com/miekg/dns v1.1.29
github.com/spf13/cobra v0.0.6
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.4.0
go.uber.org/zap v1.14.1
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
)
15 changes: 13 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg=
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
Expand Down Expand Up @@ -129,22 +131,28 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -154,6 +162,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand All @@ -164,9 +174,10 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f h1:3MlESg/jvTr87F4ttA/q4B+uhe/q6qleC9/DP+IwQmY=
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
Expand Down
44 changes: 44 additions & 0 deletions pkg/plugins/dns_mock/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
VERSION = $(shell git describe --dirty --tags --always)
DIR = $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
PKGS = $(shell go list ./...)
TEST_PKGS = $(shell find . -type f -name "*_test.go" -printf '%h\n' | sort -u)
GOARGS = GOOS=linux GOARCH=amd64
GO_BUILD_ARGS = -buildmode=plugin -ldflags="-w -s"
GO_CONTAINER_BUILD_ARGS = -buildmode=plugin -ldflags="-w -s" -a -installsuffix cgo
GO_DEBUG_BUILD_ARGS = -buildmode=plugin -gcflags "all=-N -l"
PLUGIN_NAME = $(shell basename $(DIR)).so
OUT_DIR = $(DIR)../../../plugins
DEBUG_PORT = 2345

.PHONY: deps format compile test cli-cover-report html-cover-report

all: format compile test

deps:
@go mod tidy
@go build -buildmode=plugin -v $(DIR)...

format:
@go fmt $(PKGS)

compile: deps
@mkdir -p $(OUT_DIR)
ifdef DEBUG
@echo 'Compiling for debugging...'
@$(GOARGS) go build $(GO_DEBUG_BUILD_ARGS) -o $(OUT_DIR)/$(PLUGIN_NAME) $(DIR)
else ifdef CONTAINER
@$(GOARGS) go build $(GO_CONTAINER_BUILD_ARGS) -o $(OUT_DIR)/$(PLUGIN_NAME) $(DIR)
else
@$(GOARGS) go build $(GO_BUILD_ARGS) -o $(OUT_DIR)/$(PLUGIN_NAMEs) $(DIR)
endif

test:
@go test -coverprofile=./cov-raw.out -v $(TEST_PKGS)
@cat ./cov-raw.out | grep -v "generated" > ./cov.out
@rm -f $(DIR)$(PLUGIN_NAME)

cli-cover-report:
@go tool cover -func=cov.out

html-cover-report:
@go tool cover -html=cov.out -o .coverage.html
75 changes: 75 additions & 0 deletions pkg/plugins/dns_mock/fallback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"encoding/binary"
"github.com/spf13/viper"
"math"
"math/rand"
"net"
"unsafe"
)

const (
randomIPStrategyName = "random"
incrementalIPStrategyName = "incremental"
startIPConfigKey = "startIP"
)

var (
fallbackStrategies map[string]ResolverFactory
)

type ResolverFactory func(conf *viper.Viper) ResolverFallback

func init() {
fallbackStrategies = make(map[string]ResolverFactory)
fallbackStrategies[incrementalIPStrategyName] = func(conf *viper.Viper) ResolverFallback {
return &incrementalIPFallback{
latestIp: ipToInt32(net.ParseIP(conf.GetString(startIPConfigKey))),
}
}
fallbackStrategies[randomIPStrategyName] = func(conf *viper.Viper) ResolverFallback {
return &randomIPFallback{}
}
}

func CreateResolverFallback(name string, config *viper.Viper) ResolverFallback {
if factory, ok := fallbackStrategies[name]; ok {
return factory(config)
} else {
return fallbackStrategies[randomIPStrategyName](config)
}
}

type ResolverFallback interface {
GetIP() net.IP
}

type incrementalIPFallback struct {
latestIp uint32
}

func (i *incrementalIPFallback) GetIP() net.IP {
if i.latestIp < math.MaxInt32 {
i.latestIp += 1
}
return uint32ToIP(i.latestIp)
}

type randomIPFallback struct {
}

func (randomIPFallback) GetIP() net.IP {
return uint32ToIP(uint32(rand.Int31()))
}

func uint32ToIP(i uint32) net.IP {
bytes := (*[4]byte)(unsafe.Pointer(&i))[:]
return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0])
}

func ipToInt32(ip net.IP) uint32 {
v4 := ip.To4()
result := binary.BigEndian.Uint32(v4)
return result
}
106 changes: 106 additions & 0 deletions pkg/plugins/dns_mock/fallback_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package main

import (
"net"
"reflect"
"testing"
)

func Test_randomIPFallback_GetIP(t *testing.T) {
ra := randomIPFallback{}
for i := 0; i < 1000; i++ {
if got := ra.GetIP(); reflect.DeepEqual(got, net.IP{}) {
t.Errorf("GetIP() = %v", got)
}
}
}

func Test_incrementalIPFallback_GetIP(t *testing.T) {
type fields struct {
latestIp uint32
}
tests := []struct {
name string
fields fields
want []net.IP
}{
{
name: "Expect the next icremental IP",
fields: fields{
latestIp: 167772160,
},
want: []net.IP{
net.IPv4(10, 0, 0, 1),
},
},
{
name: "Expect a sequence of 5",
fields: fields{
latestIp: 167772160,
},
want: []net.IP{
net.IPv4(10, 0, 0, 1),
net.IPv4(10, 0, 0, 2),
net.IPv4(10, 0, 0, 3),
net.IPv4(10, 0, 0, 4),
net.IPv4(10, 0, 0, 5),
},
},
{
name: "Expect next block to be incremented",
fields: fields{
latestIp: 167772413,
},
want: []net.IP{
net.IPv4(10, 0, 0, 254),
net.IPv4(10, 0, 0, 255),
net.IPv4(10, 0, 1, 0),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
i := &incrementalIPFallback{
latestIp: tt.fields.latestIp,
}
for k := 0; k < len(tt.want); k++ {
if got := i.GetIP(); !reflect.DeepEqual(got, tt.want[k]) {
t.Errorf("GetIP() = %v, want %v", got, tt.want[k])
}
}
})
}
}

func Test_ipToInt32(t *testing.T) {
type args struct {
ip net.IP
}
tests := []struct {
name string
args args
want uint32
}{
{
name: "Convert 188.193.106.113 to int",
args: args{
ip: net.ParseIP("188.193.106.113"),
},
want: 3166792305,
},
{
name: "Convert 192.168.178.10 to int",
args: args{
ip: net.ParseIP("192.168.178.10"),
},
want: 3232281098,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ipToInt32(tt.args.ip); got != tt.want {
t.Errorf("ipToInt32() = %v, want %v", got, tt.want)
}
})
}
}
25 changes: 25 additions & 0 deletions pkg/plugins/dns_mock/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"github.com/baez90/inetmock/internal/plugins"
"github.com/baez90/inetmock/pkg/api"
"github.com/baez90/inetmock/pkg/logging"
"go.uber.org/zap"
)

const (
name = "dns_mock"
)

func init() {
logger, _ := logging.CreateLogger()
logger = logger.With(
zap.String("ProtocolHandler", name),
)

plugins.Registry().RegisterHandler(name, func() api.ProtocolHandler {
return &dnsHandler{
logger: logger,
}
})
}
Loading

0 comments on commit 63ba6da

Please sign in to comment.