-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add basic DNS and DNS-over-TLS implementation
- 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
Showing
15 changed files
with
546 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
} | ||
}) | ||
} |
Oops, something went wrong.