Initial Commit

This commit is contained in:
Markus Pesch 2021-06-14 09:53:26 +02:00
commit 4a82c7db0e
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
10 changed files with 288 additions and 0 deletions

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[Makefile]
indent_style = tab

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
getpsrc

28
.golangci.yml Normal file
View File

@ -0,0 +1,28 @@
run:
skip-dirs:
- it
timeout: 10m
tests: true
linters:
disable-all: true
enable:
# Default
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
# Additionally linters
- bodyclose
- misspell
- nilerr
- rowserrcheck
- sqlclosecheck
- unparam

32
Dockerfile Normal file
View File

@ -0,0 +1,32 @@
ARG BASE_IMAGE
ARG BUILD_IMAGE
# BUILD
# =====================================================================
FROM ${BUILD_IMAGE} AS build
ARG GONOPROXY
ARG GONOSUMDB
ARG GOPRIVATE
ARG GOPROXY
ARG GOSUMDB
ARG VERSION
COPY ./ /workspace
RUN cd /workspace && \
GONOPROXY=${GONOPROXY} \
GONOSUMDB=${GONOSUMDB} \
GOPRIVATE=${GOPRIVATE} \
GOPROXY=${GOPROXY} \
GOSUMDB=${GOSUMDB} \
VERSION=${VERSION} \
make all
# TARGET
# =====================================================================
FROM ${BASE_IMAGE}
COPY --from=build /workspace/getpsrc /usr/bin/getpsrc
ENTRYPOINT [ "/usr/bin/getpsrc" ]

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
Copyright 2019 Markus Pesch
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

126
Makefile Normal file
View File

@ -0,0 +1,126 @@
# VERSION
VERSION?=$(shell git describe --abbrev=0)+hash.$(shell git rev-parse --short HEAD)
# CONTAINER_RUNTIME
CONTAINER_RUNTIME?=$(shell which docker)
# BUILD_IMAGE
BUILD_IMAGE_REGISTRY_HOST?=docker.io
BUILD_IMAGE_NAMESPACE=library
BUILD_IMAGE_REPOSITORY=golang
BUILD_IMAGE_VERSION?=1.16
BUILD_IMAGE_FULLY_QUALIFIED:=${BUILD_IMAGE_REGISTRY_HOST}/${BUILD_IMAGE_NAMESPACE}/${BUILD_IMAGE_REPOSITORY}:${BUILD_IMAGE_VERSION}
# BASE_IMAGE
BASE_IMAGE_REGISTRY_HOST?=docker.io
BASE_IMAGE_NAMESPACE=library
BASE_IMAGE_REPOSITORY=busybox
BASE_IMAGE_VERSION?=latest
BASE_IMAGE_FULLY_QUALIFIED=${BASE_IMAGE_REGISTRY_HOST}/${BASE_IMAGE_NAMESPACE}/${BASE_IMAGE_REPOSITORY}:${BASE_IMAGE_VERSION}
# CONTAINER_IMAGE
CONTAINER_IMAGE_REGISTRY_HOST?=docker.io
CONTAINER_IMAGE_NAMESPACE=volkerraschek
CONTAINER_IMAGE_REPOSITORY=getpsrc
CONTAINER_IMAGE_VERSION?=latest
CONTAINER_IMAGE_FULLY_QUALIFIED=${CONTAINER_IMAGE_REGISTRY_HOST}/${CONTAINER_IMAGE_NAMESPACE}/${CONTAINER_IMAGE_REPOSITORY}:${CONTAINER_IMAGE_VERSION}
CONTAINER_IMAGE_UNQUALIFIED=${CONTAINER_IMAGE_NAMESPACE}/${CONTAINER_IMAGE_REPOSITORY}:${CONTAINER_IMAGE_VERSION}
# EXECUTABLES
# ==============================================================================
EXECUTABLE_TARGETS=getpsrc
PHONY=all
all: clean ${EXECUTABLE_TARGETS}
getpsrc:
GOPRIVATE=$(shell go env GOPRIVATE) \
GOPROXY=$(shell go env GOPROXY) \
GONOPROXY=$(shell go env GONOPROXY) \
GONOSUMDB=$(shell go env GONOSUMDB) \
GOSUMDB=$(shell go env GOSUMDB) \
go build -tags netgo -ldflags "-X main.version=${VERSION}" -o ${@} main.go
# CLEAN
# ==============================================================================
PHONY+=clean
clean:
rm --force --recursive $(shell pwd)/getpsrc*
# GOLANGCI-LINT
# ==============================================================================
PHONY+=golangci-lint
golangci-lint:
golangci-lint run --concurrency=$(shell nproc)
# GOSEC
# ==============================================================================
PHONY+=gosec
gosec:
gosec $(shell pwd)/...
# CONTAINER-IMAGE
# ==============================================================================
PHONY+=container-image/build
container-image/build:
${CONTAINER_RUNTIME} build \
--build-arg BASE_IMAGE=${BASE_IMAGE_FULLY_QUALIFIED} \
--build-arg BUILD_IMAGE=${BUILD_IMAGE_FULLY_QUALIFIED} \
--build-arg GOPRIVATE=$(shell go env GOPRIVATE) \
--build-arg GOPROXY=$(shell go env GOPROXY) \
--build-arg GONOPROXY=$(shell go env GONOPROXY) \
--build-arg GONOSUMDB=$(shell go env GONOSUMDB) \
--build-arg GOSUMDB=$(shell go env GOSUMDB) \
--build-arg VERSION=${VERSION} \
--file ./Dockerfile \
--no-cache \
--tag ${CONTAINER_IMAGE_UNQUALIFIED} \
--tag ${CONTAINER_IMAGE_FULLY_QUALIFIED} \
.
PHONY+=container-image/push
container-image/push: container-image/build
${CONTAINER_RUNTIME} push ${CONTAINER_IMAGE_FULLY_QUALIFIED}
# CONTAINER STEPS - EXECUTABLE
# ==============================================================================
PHONY+=container-run/all
container-run/all:
$(MAKE) container-run COMMAND=${@:container-run/%=%}
PHONY+=${EXECUTABLE_TARGETS:%=container-run/%}
${EXECUTABLE_TARGETS:%=container-run/%}:
$(MAKE) container-run COMMAND=${@:container-run/%=%}
# CONTAINER STEPS - CLEAN
# ==============================================================================
PHONY+=container-run/clean
container-run/clean:
$(MAKE) container-run COMMAND=${@:container-run/%=%}
# GENERAL CONTAINER COMMAND
# ==============================================================================
PHONY+=container-run
container-run:
${CONTAINER_RUNTIME} run \
--env CONTAINER_IMAGE_VERSION=${CONTAINER_IMAGE_VERSION} \
--env GONOPROXY=$(shell go env GONOPROXY) \
--env GONOSUMDB=$(shell go env GONOSUMDB) \
--env GOPRIVATE=$(shell go env GOPRIVATE) \
--env GOPROXY=$(shell go env GOPROXY) \
--env GOSUMDB=$(shell go env GOSUMDB) \
--env VERSION=${VERSION} \
--net=host \
--rm \
--volume /tmp:/tmp \
--volume ${HOME}/go:/root/go \
--volume $(shell pwd):/workspace \
--workdir /workspace \
${BUILD_IMAGE_FULLY_QUALIFIED} \
make ${COMMAND}
# PHONY
# ==============================================================================
# Declare the contents of the PHONY variable as phony. We keep that information
# in a variable so we can use it in if_changed.
.PHONY: ${PHONY}

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# getpsrc
`getpsrc` is a small programme to determine the src routing ip for an external ip.
`getpsrc` serves as an alternative to `ip route get <ip> | awk ... ` because `ip
route get` can return different output depending on the environment and
therefore the construct is unsafe.

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/volker-raschek/getpsrc
go 1.16
require github.com/google/gopacket v1.1.20-0.20210429153827-3eaba0894325

21
go.sum Normal file
View File

@ -0,0 +1,21 @@
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/gopacket v1.1.20-0.20210429153827-3eaba0894325 h1:YmIcZ5Var3BAQ64AW98Iiys5Ih4fiU0xK41+8isC5Ec=
github.com/google/gopacket v1.1.20-0.20210429153827-3eaba0894325/go.mod h1:riddUzxTSBpJXk3qBHtYr4qOhFhT6k/1c0E3qkQjQpA=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

40
main.go Normal file
View File

@ -0,0 +1,40 @@
package main
import (
"fmt"
"log"
"net"
"os"
"strings"
"github.com/google/gopacket/routing"
)
func main() {
ips := os.Args[1:]
switch {
case len(ips) == 0:
log.Fatal("Expect exactly one argument")
case len(ips) >= 2:
log.Fatal("Expect only one argument")
}
rawIP := strings.Split(ips[0], "/")[0]
ip := net.ParseIP(rawIP)
if ip == nil {
log.Fatal("failed to parse raw ip")
}
router, err := routing.New()
if err != nil {
log.Fatalf("failed to get new routing instance: %v", err.Error())
}
_, _, prefferedSrc, err := router.Route(ip)
if err != nil {
log.Fatalf("failed to find gateway for ip: %v", err.Error())
}
fmt.Fprintln(os.Stdout, prefferedSrc.String())
}