You've already forked bird-lg-go
							
							
				mirror of
				https://github.com/xddxdd/bird-lg-go
				synced 2025-10-30 09:40:51 +01:00 
			
		
		
		
	Compare commits
	
		
			40 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 2d2193041e | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | aad8ee98d7 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 00b5c12787 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 55a1eb54fd | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0594edc69d | ||
|   | 38bf6aba09 | ||
|   | d261c22235 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 19aa8c77c5 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | fe07ebb5a5 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 66547ebfa9 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d253e4311b | ||
|   | 026498ba2f | ||
|   | 27c348a864 | ||
|   | 43b4ad93dd | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6176c45006 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 47113184f4 | ||
|   | 3c9a3e4339 | ||
|   | 8457b18d46 | ||
|   | f8f64b03a6 | ||
|   | cc818c1cc0 | ||
|   | 6224b43808 | ||
|   | 17e0b14243 | ||
|   | b4c1bed9ba | ||
|   | abb32abff3 | ||
|   | b368c75aa3 | ||
|   | 09405cdb38 | ||
|   | f999d47d9f | ||
|   | 005dfb1435 | ||
|   | 4bd7a6bb95 | ||
|   | 462d76a2d0 | ||
|   | 58f217578c | ||
|   | 0e95727de1 | ||
|   | a48f1c8040 | ||
|   | 81acde3a37 | ||
|   | 7c0fe0d512 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a5f4452d02 | ||
|   | b237185ef7 | ||
|   | e949646790 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | bb479d22ae | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d40f41b4d5 | 
| @@ -1,127 +0,0 @@ | ||||
| version: 2.1 | ||||
|  | ||||
| workflows: | ||||
|   docker: | ||||
|     jobs: | ||||
|       - build | ||||
|       - docker-frontend-deploy: | ||||
|           context: | ||||
|             - docker | ||||
|           requires: | ||||
|             - build | ||||
|           filters: | ||||
|             branches: | ||||
|               only: master | ||||
|       - docker-proxy-deploy: | ||||
|           context: | ||||
|             - docker | ||||
|           requires: | ||||
|             - build | ||||
|           filters: | ||||
|             branches: | ||||
|               only: master | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     docker: | ||||
|       - image: cimg/go:1.17 | ||||
|     working_directory: /home/circleci/go/src/github.com/xddxdd/bird-lg-go | ||||
|     steps: | ||||
|       - checkout | ||||
|       - run:  | ||||
|           name: Test frontend | ||||
|           command: | | ||||
|             export GO111MODULE=on | ||||
|             cd frontend | ||||
|             go get -v -t -d ./... | ||||
|             go test -v ./... | ||||
|       - run:  | ||||
|           name: Test proxy | ||||
|           command: | | ||||
|             export GO111MODULE=on | ||||
|             cd proxy | ||||
|             go get -v -t -d ./... | ||||
|             go test -v ./... | ||||
|  | ||||
|   docker-frontend-deploy: | ||||
|     machine: | ||||
|       image: ubuntu-2004:202111-02 | ||||
|     environment: | ||||
|       BUILDX_PLATFORMS: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|     steps: | ||||
|       - checkout | ||||
|       - run: | ||||
|           name: Install buildx | ||||
|           command: | | ||||
|             BUILDX_BINARY_URL="https://github.com/docker/buildx/releases/download/v0.7.1/buildx-v0.7.1.linux-amd64" | ||||
|  | ||||
|             curl --output docker-buildx \ | ||||
|               --silent --show-error --location --fail --retry 3 \ | ||||
|               "$BUILDX_BINARY_URL" | ||||
|  | ||||
|             mkdir -p ~/.docker/cli-plugins | ||||
|  | ||||
|             mv docker-buildx ~/.docker/cli-plugins/ | ||||
|             chmod a+x ~/.docker/cli-plugins/docker-buildx | ||||
|  | ||||
|             docker buildx install | ||||
|             # Run binfmt | ||||
|             docker run --rm --privileged multiarch/qemu-user-static --reset -p yes | ||||
|       - run: | ||||
|           name: Build Docker image | ||||
|           environment: | ||||
|             BUILD_ID: << pipeline.number >> | ||||
|           command: | | ||||
|             echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin | ||||
|             docker buildx create --name mybuilder --use | ||||
|             docker buildx build \ | ||||
|               --platform $BUILDX_PLATFORMS \ | ||||
|               -t $DOCKER_USERNAME/bird-lg-go:circleci-build$BUILD_ID \ | ||||
|               --progress plain \ | ||||
|               --push frontend | ||||
|             docker buildx build \ | ||||
|               --platform $BUILDX_PLATFORMS \ | ||||
|               -t $DOCKER_USERNAME/bird-lg-go:latest \ | ||||
|               --progress plain \ | ||||
|               --push frontend | ||||
|  | ||||
|   docker-proxy-deploy: | ||||
|     machine: | ||||
|       image: ubuntu-2004:202111-02 | ||||
|     environment: | ||||
|       BUILDX_PLATFORMS: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|     steps: | ||||
|       - checkout | ||||
|       - run: | ||||
|           name: Install buildx | ||||
|           command: | | ||||
|             BUILDX_BINARY_URL="https://github.com/docker/buildx/releases/download/v0.7.1/buildx-v0.7.1.linux-amd64" | ||||
|  | ||||
|             curl --output docker-buildx \ | ||||
|               --silent --show-error --location --fail --retry 3 \ | ||||
|               "$BUILDX_BINARY_URL" | ||||
|  | ||||
|             mkdir -p ~/.docker/cli-plugins | ||||
|  | ||||
|             mv docker-buildx ~/.docker/cli-plugins/ | ||||
|             chmod a+x ~/.docker/cli-plugins/docker-buildx | ||||
|  | ||||
|             docker buildx install | ||||
|             # Run binfmt | ||||
|             docker run --rm --privileged multiarch/qemu-user-static --reset -p yes | ||||
|       - run: | ||||
|           name: Build Docker image | ||||
|           environment: | ||||
|             BUILD_ID: << pipeline.number >> | ||||
|           command: | | ||||
|             echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin | ||||
|             docker buildx create --name mybuilder --use | ||||
|             docker buildx build \ | ||||
|               --platform $BUILDX_PLATFORMS \ | ||||
|               -t $DOCKER_USERNAME/bird-lgproxy-go:circleci-build$BUILD_ID \ | ||||
|               --push proxy | ||||
|             docker buildx build \ | ||||
|               --platform $BUILDX_PLATFORMS \ | ||||
|               -t $DOCKER_USERNAME/bird-lgproxy-go:latest \ | ||||
|               --progress plain \ | ||||
|               --push proxy | ||||
							
								
								
									
										16
									
								
								.github/workflows/auto-merge.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/auto-merge.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| name: auto-merge | ||||
|  | ||||
| on: | ||||
|   pull_request_target: | ||||
|  | ||||
| jobs: | ||||
|   auto-merge: | ||||
|     name: Dependabot Auto Merge | ||||
|     runs-on: ubuntu-latest | ||||
|     if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - uses: ahmadnassri/action-dependabot-auto-merge@v2 | ||||
|         with: | ||||
|           target: minor | ||||
|           github-token: ${{ secrets.AUTOMERGE_TOKEN }} | ||||
							
								
								
									
										108
									
								
								.github/workflows/develop.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								.github/workflows/develop.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - 'master' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - 'master' | ||||
|  | ||||
| jobs: | ||||
|   go-test: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Setup Golang | ||||
|         uses: actions/setup-go@v4 | ||||
|  | ||||
|       - name: Run frontend unit test | ||||
|         run: | | ||||
|           export GO111MODULE=on | ||||
|           cd frontend | ||||
|           go get -v -t -d ./... | ||||
|           go test -v ./... | ||||
|           cd .. | ||||
|  | ||||
|       - name: Run proxy unit test | ||||
|         run: | | ||||
|           export GO111MODULE=on | ||||
|           cd proxy | ||||
|           go get -v -t -d ./... | ||||
|           go test -v ./... | ||||
|           cd .. | ||||
|  | ||||
|   docker-test: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|  | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|  | ||||
|       - name: Test whois binary in frontend image | ||||
|         run: | | ||||
|           docker build -t local/frontend frontend/ | ||||
|           docker run --rm --net host --entrypoint whois local/frontend github.com || exit 1 | ||||
|           docker run --rm --net host --entrypoint whois local/frontend -h whois.ripe.net github.com || exit 1 | ||||
|           docker run --rm --net host --entrypoint whois local/frontend -h whois.ripe.net:43 github.com || exit 1 | ||||
|  | ||||
|       - name: Test traceroute binary in proxy image | ||||
|         run: | | ||||
|           docker build -t local/proxy proxy/ | ||||
|           docker run --rm --net host --entrypoint traceroute local/proxy 127.0.0.1 || exit 1 | ||||
|           docker run --rm --net host --entrypoint traceroute local/proxy ::1 || exit 1 | ||||
|  | ||||
|   docker-develop: | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: | ||||
|       - go-test | ||||
|       - docker-test | ||||
|     if: github.event_name != 'pull_request' | ||||
|     steps: | ||||
|       - name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|  | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|  | ||||
|       - name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|  | ||||
|       - name: Login to GitHub Container Registry | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ github.repository_owner }} | ||||
|           password: ${{ secrets.GITHUB_TOKEN }} | ||||
|  | ||||
|       - name: Build frontend docker image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           context: '{{defaultContext}}:frontend' | ||||
|           platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|           push: true | ||||
|           tags: | | ||||
|             xddxdd/bird-lg-go:develop | ||||
|             xddxdd/bird-lg-go:develop-${{ github.sha }} | ||||
|             ghcr.io/xddxdd/bird-lg-go:frontend-develop | ||||
|             ghcr.io/xddxdd/bird-lg-go:frontend-develop-${{ github.sha }} | ||||
|  | ||||
|       - name: Build proxy docker image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           context: '{{defaultContext}}:proxy' | ||||
|           platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|           push: true | ||||
|           tags: | | ||||
|             xddxdd/bird-lgproxy-go:develop | ||||
|             xddxdd/bird-lgproxy-go:develop-${{ github.sha }} | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-develop | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-develop-${{ github.sha }} | ||||
							
								
								
									
										60
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										60
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -3,10 +3,11 @@ on: | ||||
|     types: [created] | ||||
|  | ||||
| jobs: | ||||
|   releases-matrix: | ||||
|   go-release: | ||||
|     name: Release Go Binary | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         goos: [linux, windows, darwin] | ||||
|         goarch: ["386", amd64, "arm", arm64] | ||||
| @@ -18,18 +19,69 @@ jobs: | ||||
|           - goarch: "arm" | ||||
|             goos: windows | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|     - uses: wangyoucao577/go-release-action@v1.34 | ||||
|     - name: Checkout | ||||
|       uses: actions/checkout@v3 | ||||
|  | ||||
|     - name: Release frontend | ||||
|       uses: wangyoucao577/go-release-action@v1.40 | ||||
|       with: | ||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|         goos: ${{ matrix.goos }} | ||||
|         goarch: ${{ matrix.goarch }} | ||||
|         project_path: "./frontend" | ||||
|         binary_name: "bird-lg-go" | ||||
|     - uses: wangyoucao577/go-release-action@v1.34 | ||||
|  | ||||
|     - name: Release proxy | ||||
|       uses: wangyoucao577/go-release-action@v1.40 | ||||
|       with: | ||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|         goos: ${{ matrix.goos }} | ||||
|         goarch: ${{ matrix.goarch }} | ||||
|         project_path: "./proxy" | ||||
|         binary_name: "bird-lgproxy-go" | ||||
|  | ||||
|   docker-release: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Set up QEMU | ||||
|         uses: docker/setup-qemu-action@v2 | ||||
|  | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|  | ||||
|       - name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||
|           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||
|  | ||||
|       - name: Login to GitHub Container Registry | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           registry: ghcr.io | ||||
|           username: ${{ github.repository_owner }} | ||||
|           password: ${{ secrets.GITHUB_TOKEN }} | ||||
|  | ||||
|       - name: Build frontend docker image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           context: '{{defaultContext}}:frontend' | ||||
|           platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|           push: true | ||||
|           tags: | | ||||
|             xddxdd/bird-lg-go:latest | ||||
|             xddxdd/bird-lg-go:${{ github.event.release.tag_name }} | ||||
|             ghcr.io/xddxdd/bird-lg-go:frontend | ||||
|             ghcr.io/xddxdd/bird-lg-go:frontend-${{ github.event.release.tag_name }} | ||||
|  | ||||
|       - name: Build proxy docker image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           context: '{{defaultContext}}:proxy' | ||||
|           platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|           push: true | ||||
|           tags: | | ||||
|             xddxdd/bird-lgproxy-go:latest | ||||
|             xddxdd/bird-lgproxy-go:${{ github.event.release.tag_name }} | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-${{ github.event.release.tag_name }} | ||||
|   | ||||
| @@ -90,7 +90,8 @@ Example: the following docker-compose.yml entry does the same as above, but by s | ||||
| ```yaml | ||||
| services: | ||||
|   bird-lg: | ||||
|     image: xddxdd/bird-lg-go | ||||
|     # Use xddxdd/bird-lg-go:develop for the latest build from master branch | ||||
|     image: xddxdd/bird-lg-go:latest | ||||
|     container_name: bird-lg | ||||
|     restart: always | ||||
|     environment: | ||||
| @@ -124,7 +125,7 @@ Configuration is handled by [viper](https://github.com/spf13/viper), any config | ||||
|  | ||||
| | Config Key | Parameter | Environment Variable | Description | | ||||
| | ---------- | --------- | -------------------- | ----------- | | ||||
| | allowed_ips | --allowed | ALLOWED_IPS | IPs allowed to access this proxy, separated by commas. Don't set to allow all IPs. (default "") | | ||||
| | allowed_ips | --allowed | ALLOWED_IPS | IPs or networks allowed to access this proxy, separated by commas. Don't set to allow all IPs. (default "") | | ||||
| | bird_socket | --bird | BIRD_SOCKET | socket file for bird, set either in parameter or environment variable BIRD_SOCKET (default "/var/run/bird/bird.ctl") | | ||||
| | listen | --listen | BIRDLG_PROXY_PORT | listen address, set either in parameter or environment variable  BIRDLG_PROXY_PORT(default "8000") | | ||||
| | traceroute_bin | --traceroute_bin | BIRDLG_TRACEROUTE_BIN | traceroute binary file, set either in parameter or environment variable  BIRDLG_TRACEROUTE_BIN | | ||||
| @@ -165,7 +166,8 @@ Example: the following docker-compose.yml entry does the same as above, but by s | ||||
| ```yaml | ||||
| services: | ||||
|   bird-lgproxy: | ||||
|     image: xddxdd/bird-lgproxy-go | ||||
|     # Use xddxdd/bird-lgproxy-go:develop for the latest build from master branch | ||||
|     image: xddxdd/bird-lgproxy-go:latest | ||||
|     container_name: bird-lgproxy | ||||
|     restart: always | ||||
|     volumes: | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| FROM golang:buster AS step_0 | ||||
| FROM golang AS step_0 | ||||
| ENV CGO_ENABLED=0 GO111MODULE=on | ||||
| WORKDIR /root | ||||
| COPY . . | ||||
| @@ -6,6 +6,28 @@ RUN go build -ldflags "-w -s" -o /frontend | ||||
|  | ||||
| ################################################################################ | ||||
|  | ||||
| FROM scratch AS step_1 | ||||
| FROM alpine:edge AS step_1 | ||||
|  | ||||
| WORKDIR /root | ||||
| RUN apk add --no-cache build-base pkgconf perl gettext \ | ||||
|     libidn2-dev libidn2-static libunistring-dev libunistring-static gnu-libiconv-dev | ||||
|  | ||||
| RUN wget https://github.com/rfc1036/whois/archive/refs/tags/v5.5.18.tar.gz \ | ||||
|     -O whois-5.5.18.tar.gz | ||||
|  | ||||
| RUN tar xvf whois-5.5.18.tar.gz \ | ||||
|     && cd whois-5.5.18 \ | ||||
|     && sed -i "s/#if defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L/#if 1/g" config.h \ | ||||
|     && make whois -j4 \ | ||||
|       LDFLAGS="-static" CONFIG_FILE="/etc/whois.conf" PKG_CONFIG="pkg-config --static" HAVE_ICONV=1 \ | ||||
|     && strip /root/whois-5.5.18/whois | ||||
|  | ||||
| ################################################################################ | ||||
|  | ||||
| FROM scratch AS step_2 | ||||
| ENV PATH=/ | ||||
| ENV BIRDLG_WHOIS=/whois | ||||
| COPY --from=step_0 /frontend / | ||||
| COPY --from=step_1 /root/whois-5.5.18/whois / | ||||
| COPY --from=step_1 /etc/services /etc/services | ||||
| ENTRYPOINT ["/frontend"] | ||||
|   | ||||
| @@ -60,7 +60,7 @@ | ||||
| 					<option value="{{ html $k }}"{{ if eq $k $.URLOption }} selected{{end}}>{{ html $v }}</option> | ||||
| 					{{ end }} | ||||
| 				</select> | ||||
| 				<input name="server" class="d-none" value="{{ html $server }}"> | ||||
| 				<input name="server" class="d-none" value="{{ html ($server | pathescape) }}"> | ||||
| 				<input name="target" class="form-control" placeholder="Target" aria-label="Target" value="{{ html $target }}"> | ||||
| 				<div class="input-group-append"> | ||||
| 					<button class="btn btn-outline-success" type="submit">»</button> | ||||
|   | ||||
| @@ -3,27 +3,31 @@ module github.com/xddxdd/bird-lg-go/frontend | ||||
| go 1.17 | ||||
|  | ||||
| require ( | ||||
| 	github.com/gorilla/handlers v1.5.1 | ||||
| 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 | ||||
| 	github.com/gorilla/handlers v1.5.2 | ||||
| 	github.com/jarcoal/httpmock v1.3.1 | ||||
| 	github.com/magiconair/properties v1.8.7 | ||||
| 	github.com/spf13/pflag v1.0.5 | ||||
| 	github.com/spf13/viper v1.15.0 | ||||
| 	github.com/spf13/viper v1.18.0 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	github.com/felixge/httpsnoop v1.0.3 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.6.0 // indirect | ||||
| 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.7.0 // indirect | ||||
| 	github.com/hashicorp/hcl v1.0.0 // indirect | ||||
| 	github.com/jarcoal/httpmock v1.3.0 // indirect | ||||
| 	github.com/magiconair/properties v1.8.7 // indirect | ||||
| 	github.com/mitchellh/mapstructure v1.5.0 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect | ||||
| 	github.com/spf13/afero v1.9.3 // indirect | ||||
| 	github.com/spf13/cast v1.5.0 // indirect | ||||
| 	github.com/spf13/jwalterweatherman v1.1.0 // indirect | ||||
| 	github.com/subosito/gotenv v1.4.2 // indirect | ||||
| 	golang.org/x/sys v0.3.0 // indirect | ||||
| 	golang.org/x/text v0.5.0 // indirect | ||||
| 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.1.0 // indirect | ||||
| 	github.com/sagikazarmark/locafero v0.4.0 // indirect | ||||
| 	github.com/sagikazarmark/slog-shim v0.1.0 // indirect | ||||
| 	github.com/sourcegraph/conc v0.3.0 // indirect | ||||
| 	github.com/spf13/afero v1.11.0 // indirect | ||||
| 	github.com/spf13/cast v1.6.0 // indirect | ||||
| 	github.com/subosito/gotenv v1.6.0 // indirect | ||||
| 	go.uber.org/atomic v1.9.0 // indirect | ||||
| 	go.uber.org/multierr v1.9.0 // indirect | ||||
| 	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect | ||||
| 	golang.org/x/sys v0.15.0 // indirect | ||||
| 	golang.org/x/text v0.14.0 // indirect | ||||
| 	gopkg.in/ini.v1 v1.67.0 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| ) | ||||
|   | ||||
							
								
								
									
										1285
									
								
								frontend/go.sum
									
									
									
									
									
								
							
							
						
						
									
										1285
									
								
								frontend/go.sum
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -2,11 +2,14 @@ package main | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/jarcoal/httpmock" | ||||
| ) | ||||
|  | ||||
| type channelData struct { | ||||
| @@ -14,6 +17,29 @@ type channelData struct { | ||||
| 	data string | ||||
| } | ||||
|  | ||||
| func createConnectionTimeoutRoundTripper(timeout int) http.RoundTripper { | ||||
| 	context := net.Dialer{ | ||||
| 		Timeout: time.Duration(timeout) * time.Second, | ||||
| 	} | ||||
|  | ||||
| 	// Prefer httpmock's transport if activated, so unit tests can work | ||||
| 	if http.DefaultTransport == httpmock.DefaultTransport { | ||||
| 		return httpmock.DefaultTransport | ||||
| 	} | ||||
|  | ||||
| 	return &http.Transport{ | ||||
| 		DialContext: context.DialContext, | ||||
|  | ||||
| 		// Default options from transport.go | ||||
| 		Proxy:                 http.ProxyFromEnvironment, | ||||
| 		ForceAttemptHTTP2:     true, | ||||
| 		MaxIdleConns:          100, | ||||
| 		IdleConnTimeout:       90 * time.Second, | ||||
| 		TLSHandshakeTimeout:   10 * time.Second, | ||||
| 		ExpectContinueTimeout: 1 * time.Second, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Send commands to lgproxy instances in parallel, and retrieve their responses | ||||
| func batchRequest(servers []string, endpoint string, command string) []string { | ||||
| 	// Channel and array for storing responses | ||||
| @@ -47,7 +73,10 @@ func batchRequest(servers []string, endpoint string, command string) []string { | ||||
| 			} | ||||
| 			url := "http://" + hostname + ":" + strconv.Itoa(setting.proxyPort) + "/" + url.PathEscape(endpoint) + "?q=" + url.QueryEscape(command) | ||||
| 			go func(url string, i int) { | ||||
| 				client := http.Client{Timeout: time.Duration(setting.timeOut) * time.Second} | ||||
| 				client := http.Client{ | ||||
| 					Transport: createConnectionTimeoutRoundTripper(setting.connectionTimeOut), | ||||
| 					Timeout:   time.Duration(setting.timeOut) * time.Second, | ||||
| 				} | ||||
| 				response, err := client.Get(url) | ||||
| 				if err != nil { | ||||
| 					ch <- channelData{i, "request failed: " + err.Error() + "\n"} | ||||
|   | ||||
| @@ -7,24 +7,25 @@ import ( | ||||
| ) | ||||
|  | ||||
| type settingType struct { | ||||
| 	servers         []string | ||||
| 	serversDisplay  []string | ||||
| 	domain          string | ||||
| 	proxyPort       int | ||||
| 	whoisServer     string | ||||
| 	listen          string | ||||
| 	dnsInterface    string | ||||
| 	netSpecificMode string | ||||
| 	titleBrand      string | ||||
| 	navBarBrand     string | ||||
| 	navBarBrandURL  string | ||||
| 	navBarAllServer string | ||||
| 	navBarAllURL    string | ||||
| 	bgpmapInfo      string | ||||
| 	telegramBotName string | ||||
| 	protocolFilter  []string | ||||
| 	nameFilter      string | ||||
| 	timeOut         int | ||||
| 	servers           []string | ||||
| 	serversDisplay    []string | ||||
| 	domain            string | ||||
| 	proxyPort         int | ||||
| 	whoisServer       string | ||||
| 	listen            string | ||||
| 	dnsInterface      string | ||||
| 	netSpecificMode   string | ||||
| 	titleBrand        string | ||||
| 	navBarBrand       string | ||||
| 	navBarBrandURL    string | ||||
| 	navBarAllServer   string | ||||
| 	navBarAllURL      string | ||||
| 	bgpmapInfo        string | ||||
| 	telegramBotName   string | ||||
| 	protocolFilter    []string | ||||
| 	nameFilter        string | ||||
| 	timeOut           int | ||||
| 	connectionTimeOut int | ||||
| } | ||||
|  | ||||
| var setting settingType | ||||
|   | ||||
| @@ -9,23 +9,24 @@ import ( | ||||
| ) | ||||
|  | ||||
| type viperSettingType struct { | ||||
| 	Servers         string `mapstructure:"servers"` | ||||
| 	Domain          string `mapstructure:"domain"` | ||||
| 	ProxyPort       int    `mapstructure:"proxy_port"` | ||||
| 	WhoisServer     string `mapstructure:"whois"` | ||||
| 	Listen          string `mapstructure:"listen"` | ||||
| 	DNSInterface    string `mapstructure:"dns_interface"` | ||||
| 	NetSpecificMode string `mapstructure:"net_specific_mode"` | ||||
| 	TitleBrand      string `mapstructure:"title_brand"` | ||||
| 	NavBarBrand     string `mapstructure:"navbar_brand"` | ||||
| 	NavBarBrandURL  string `mapstructure:"navbar_brand_url"` | ||||
| 	NavBarAllServer string `mapstructure:"navbar_all_servers"` | ||||
| 	NavBarAllURL    string `mapstructure:"navbar_all_url"` | ||||
| 	BgpmapInfo      string `mapstructure:"bgpmap_info"` | ||||
| 	TelegramBotName string `mapstructure:"telegram_bot_name"` | ||||
| 	ProtocolFilter  string `mapstructure:"protocol_filter"` | ||||
| 	NameFilter      string `mapstructure:"name_filter"` | ||||
| 	TimeOut         int    `mapstructure:"timeout"` | ||||
| 	Servers           string `mapstructure:"servers"` | ||||
| 	Domain            string `mapstructure:"domain"` | ||||
| 	ProxyPort         int    `mapstructure:"proxy_port"` | ||||
| 	WhoisServer       string `mapstructure:"whois"` | ||||
| 	Listen            string `mapstructure:"listen"` | ||||
| 	DNSInterface      string `mapstructure:"dns_interface"` | ||||
| 	NetSpecificMode   string `mapstructure:"net_specific_mode"` | ||||
| 	TitleBrand        string `mapstructure:"title_brand"` | ||||
| 	NavBarBrand       string `mapstructure:"navbar_brand"` | ||||
| 	NavBarBrandURL    string `mapstructure:"navbar_brand_url"` | ||||
| 	NavBarAllServer   string `mapstructure:"navbar_all_servers"` | ||||
| 	NavBarAllURL      string `mapstructure:"navbar_all_url"` | ||||
| 	BgpmapInfo        string `mapstructure:"bgpmap_info"` | ||||
| 	TelegramBotName   string `mapstructure:"telegram_bot_name"` | ||||
| 	ProtocolFilter    string `mapstructure:"protocol_filter"` | ||||
| 	NameFilter        string `mapstructure:"name_filter"` | ||||
| 	TimeOut           int    `mapstructure:"timeout"` | ||||
| 	ConnectionTimeOut int    `mapstructure:"connection_timeout"` | ||||
| } | ||||
|  | ||||
| // Parse settings with viper, and convert to legacy setting format | ||||
| @@ -87,9 +88,12 @@ func parseSettings() { | ||||
| 	pflag.String("name-filter", "", "protocol name regex to hide in summary tables (RE2 syntax); defaults to none if not set") | ||||
| 	viper.BindPFlag("name_filter", pflag.Lookup("name-filter")) | ||||
|  | ||||
| 	pflag.Int("time-out", 120, "time before request timed out, in seconds; defaults to 120 if not set") | ||||
| 	pflag.Int("time-out", 120, "time before backend HTTP request times out, in seconds; defaults to 120 if not set") | ||||
| 	viper.BindPFlag("timeout", pflag.Lookup("time-out")) | ||||
|  | ||||
| 	pflag.Int("connection-time-out", 5, "time before backend TCP connection times out, in seconds; defaults to 5 if not set") | ||||
| 	viper.BindPFlag("connection_timeout", pflag.Lookup("connection-time-out")) | ||||
|  | ||||
| 	pflag.Parse() | ||||
|  | ||||
| 	if err := viper.ReadInConfig(); err != nil { | ||||
| @@ -139,6 +143,7 @@ func parseSettings() { | ||||
|  | ||||
| 	setting.nameFilter = viperSettings.NameFilter | ||||
| 	setting.timeOut = viperSettings.TimeOut | ||||
| 	setting.connectionTimeOut = viperSettings.ConnectionTimeOut | ||||
|  | ||||
| 	fmt.Printf("%#v\n", setting) | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package main | ||||
| import ( | ||||
| 	"embed" | ||||
| 	"html/template" | ||||
|         "net/url" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| @@ -104,6 +105,12 @@ var requiredTemplates = [...]string{ | ||||
| 	"bird", | ||||
| } | ||||
|  | ||||
| // define functions to be made available in templates | ||||
|  | ||||
| var funcMap = template.FuncMap{ | ||||
|         "pathescape": url.PathEscape, | ||||
| } | ||||
|  | ||||
| // import templates from embedded assets | ||||
|  | ||||
| func ImportTemplates() { | ||||
| @@ -121,7 +128,7 @@ func ImportTemplates() { | ||||
| 		} | ||||
|  | ||||
| 		// and add it to the template library | ||||
| 		template, err := template.New(tmpl).Parse(string(def)) | ||||
| 		template, err := template.New(tmpl).Funcs(funcMap).Parse(string(def)) | ||||
| 		if err != nil { | ||||
| 			panic("Unable to parse template (" + TEMPLATE_PATH + tmpl + ": " + err.Error()) | ||||
| 		} | ||||
|   | ||||
| @@ -25,13 +25,14 @@ func whois(s string) string { | ||||
|  | ||||
| 		cmd := exec.Command(args[0], args[1:]...) | ||||
| 		output, err := cmd.CombinedOutput() | ||||
| 		if err != nil { | ||||
| 			return err.Error() | ||||
| 		} | ||||
| 		if len(output) > 65535 { | ||||
| 			output = output[:65535] | ||||
| 		} | ||||
| 		return string(output) | ||||
| 		if err != nil { | ||||
| 			return err.Error() + "\n" + string(output) | ||||
| 		} else { | ||||
| 			return string(output) | ||||
| 		} | ||||
| 	} else { | ||||
| 		buf := make([]byte, 65536) | ||||
|  | ||||
| @@ -50,7 +51,7 @@ func whois(s string) string { | ||||
|  | ||||
| 		n, err := io.ReadFull(conn, buf) | ||||
| 		if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { | ||||
| 			return err.Error() | ||||
| 			return err.Error() + "\n" + string(buf[:n]) | ||||
| 		} | ||||
| 		return string(buf[:n]) | ||||
| 	} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| FROM golang:buster AS step_0 | ||||
| FROM golang AS step_0 | ||||
|  | ||||
| ENV CGO_ENABLED=0 GO111MODULE=on | ||||
| WORKDIR /root | ||||
| @@ -11,17 +11,18 @@ FROM alpine:edge AS step_1 | ||||
|  | ||||
| WORKDIR /root | ||||
| RUN apk add --no-cache build-base linux-headers | ||||
| RUN wget https://sourceforge.net/projects/traceroute/files/traceroute/traceroute-2.1.0/traceroute-2.1.0.tar.gz/download \ | ||||
|     -O traceroute-2.1.0.tar.gz | ||||
| RUN tar xvf traceroute-2.1.0.tar.gz \ | ||||
|     && cd traceroute-2.1.0 \ | ||||
|  | ||||
| RUN wget https://sourceforge.net/projects/traceroute/files/traceroute/traceroute-2.1.3/traceroute-2.1.3.tar.gz/download \ | ||||
|     -O traceroute-2.1.3.tar.gz | ||||
| RUN tar xvf traceroute-2.1.3.tar.gz \ | ||||
|     && cd traceroute-2.1.3 \ | ||||
|     && make -j4 LDFLAGS="-static" \ | ||||
|     && strip /root/traceroute-2.1.0/traceroute/traceroute | ||||
|     && strip /root/traceroute-2.1.3/traceroute/traceroute | ||||
|  | ||||
| ################################################################################ | ||||
|  | ||||
| FROM scratch AS step_2 | ||||
| ENV PATH=/ | ||||
| COPY --from=step_0 /proxy / | ||||
| COPY --from=step_1 /root/traceroute-2.1.0/traceroute/traceroute / | ||||
| COPY --from=step_1 /root/traceroute-2.1.3/traceroute/traceroute / | ||||
| ENTRYPOINT ["/proxy"] | ||||
|   | ||||
							
								
								
									
										28
									
								
								proxy/go.mod
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								proxy/go.mod
									
									
									
									
									
								
							| @@ -4,25 +4,29 @@ go 1.17 | ||||
|  | ||||
| require ( | ||||
| 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 | ||||
| 	github.com/gorilla/handlers v1.5.1 | ||||
| 	github.com/gorilla/handlers v1.5.2 | ||||
| 	github.com/magiconair/properties v1.8.7 | ||||
| 	github.com/spf13/pflag v1.0.5 | ||||
| 	github.com/spf13/viper v1.15.0 | ||||
| 	github.com/spf13/viper v1.18.0 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	github.com/felixge/httpsnoop v1.0.3 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.6.0 // indirect | ||||
| 	github.com/fsnotify/fsnotify v1.7.0 // indirect | ||||
| 	github.com/hashicorp/hcl v1.0.0 // indirect | ||||
| 	github.com/magiconair/properties v1.8.7 // indirect | ||||
| 	github.com/mitchellh/mapstructure v1.5.0 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect | ||||
| 	github.com/spf13/afero v1.9.3 // indirect | ||||
| 	github.com/spf13/cast v1.5.0 // indirect | ||||
| 	github.com/spf13/jwalterweatherman v1.1.0 // indirect | ||||
| 	github.com/subosito/gotenv v1.4.2 // indirect | ||||
| 	golang.org/x/sys v0.3.0 // indirect | ||||
| 	golang.org/x/text v0.5.0 // indirect | ||||
| 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.1.0 // indirect | ||||
| 	github.com/sagikazarmark/locafero v0.4.0 // indirect | ||||
| 	github.com/sagikazarmark/slog-shim v0.1.0 // indirect | ||||
| 	github.com/sourcegraph/conc v0.3.0 // indirect | ||||
| 	github.com/spf13/afero v1.11.0 // indirect | ||||
| 	github.com/spf13/cast v1.6.0 // indirect | ||||
| 	github.com/subosito/gotenv v1.6.0 // indirect | ||||
| 	go.uber.org/atomic v1.9.0 // indirect | ||||
| 	go.uber.org/multierr v1.9.0 // indirect | ||||
| 	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect | ||||
| 	golang.org/x/sys v0.15.0 // indirect | ||||
| 	golang.org/x/text v0.14.0 // indirect | ||||
| 	gopkg.in/ini.v1 v1.67.0 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| ) | ||||
|   | ||||
							
								
								
									
										1279
									
								
								proxy/go.sum
									
									
									
									
									
								
							
							
						
						
									
										1279
									
								
								proxy/go.sum
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -22,8 +22,8 @@ func invalidHandler(httpW http.ResponseWriter, httpR *http.Request) { | ||||
| } | ||||
|  | ||||
| func hasAccess(remoteAddr string) bool { | ||||
| 	// setting.allowedIPs will always have at least one element because of how it's defined | ||||
| 	if len(setting.allowedIPs) == 0 { | ||||
| 	// setting.allowedNets will always have at least one element because of how it's defined | ||||
| 	if len(setting.allowedNets) == 0 { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| @@ -40,8 +40,8 @@ func hasAccess(remoteAddr string) bool { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	for _, allowedIP := range setting.allowedIPs { | ||||
| 		if ipObject.Equal(allowedIP) { | ||||
| 	for _, net := range setting.allowedNets { | ||||
| 		if net.Contains(ipObject) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| @@ -49,7 +49,7 @@ func hasAccess(remoteAddr string) bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // Access handler, check to see if client IP in allowed IPs, continue if it is, send to invalidHandler if not | ||||
| // Access handler, check to see if client IP in allowed nets, continue if it is, send to invalidHandler if not | ||||
| func accessHandler(next http.Handler) http.Handler { | ||||
| 	return http.HandlerFunc(func(httpW http.ResponseWriter, httpR *http.Request) { | ||||
| 		if hasAccess(httpR.RemoteAddr) { | ||||
| @@ -61,12 +61,12 @@ func accessHandler(next http.Handler) http.Handler { | ||||
| } | ||||
|  | ||||
| type settingType struct { | ||||
| 	birdSocket string | ||||
| 	listen     string | ||||
| 	allowedIPs []net.IP | ||||
| 	tr_bin     string | ||||
| 	tr_flags   []string | ||||
| 	tr_raw     bool | ||||
| 	birdSocket  string | ||||
| 	listen      string | ||||
| 	allowedNets []*net.IPNet | ||||
| 	tr_bin      string | ||||
| 	tr_flags    []string | ||||
| 	tr_raw      bool | ||||
| } | ||||
|  | ||||
| var setting settingType | ||||
|   | ||||
| @@ -10,42 +10,61 @@ import ( | ||||
| ) | ||||
|  | ||||
| func TestHasAccessNotConfigured(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{} | ||||
| 	setting.allowedNets = []*net.IPNet{} | ||||
| 	assert.Equal(t, hasAccess("whatever"), true) | ||||
| } | ||||
|  | ||||
| func TestHasAccessAllowIPv4(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("1.2.3.4")} | ||||
| 	_, netip, _ := net.ParseCIDR("1.2.3.4/32") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("1.2.3.4:4321"), true) | ||||
| } | ||||
|  | ||||
| func TestHasAccessAllowIPv4Net(t *testing.T) { | ||||
| 	_, netip, _ := net.ParseCIDR("1.2.3.0/24") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("1.2.3.4:4321"), true) | ||||
| } | ||||
|  | ||||
| func TestHasAccessDenyIPv4(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("4.3.2.1")} | ||||
| 	_, netip, _ := net.ParseCIDR("4.3.2.1/32") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("1.2.3.4:4321"), false) | ||||
| } | ||||
|  | ||||
| func TestHasAccessAllowIPv6(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("2001:db8::1")} | ||||
| 	_, netip, _ := net.ParseCIDR("2001:db8::1/128") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("[2001:db8::1]:4321"), true) | ||||
| } | ||||
|  | ||||
| func TestHasAccessAllowIPv6Net(t *testing.T) { | ||||
| 	_, netip, _ := net.ParseCIDR("2001:db8::/64") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("[2001:db8::1]:4321"), true) | ||||
| } | ||||
|  | ||||
| func TestHasAccessAllowIPv6DifferentForm(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("2001:0db8::1")} | ||||
| 	_, netip, _ := net.ParseCIDR("2001:db8::1/128") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("[2001:db8::1]:4321"), true) | ||||
| } | ||||
|  | ||||
| func TestHasAccessDenyIPv6(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("2001:db8::2")} | ||||
| 	_, netip, _ := net.ParseCIDR("2001:db8::2/128") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("[2001:db8::1]:4321"), false) | ||||
| } | ||||
|  | ||||
| func TestHasAccessBadClientIP(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("1.2.3.4")} | ||||
| 	_, netip, _ := net.ParseCIDR("1.2.3.4/32") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("not an IP"), false) | ||||
| } | ||||
|  | ||||
| func TestHasAccessBadClientIPPort(t *testing.T) { | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("1.2.3.4")} | ||||
| 	_, netip, _ := net.ParseCIDR("1.2.3.4/32") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
| 	assert.Equal(t, hasAccess("not an IP:not a port"), false) | ||||
| } | ||||
|  | ||||
| @@ -57,7 +76,8 @@ func TestAccessHandlerAllow(t *testing.T) { | ||||
| 	r.RemoteAddr = "1.2.3.4:4321" | ||||
| 	w := httptest.NewRecorder() | ||||
|  | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("1.2.3.4")} | ||||
| 	_, netip, _ := net.ParseCIDR("1.2.3.4/32") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
|  | ||||
| 	wrappedHandler.ServeHTTP(w, r) | ||||
| 	assert.Equal(t, w.Code, http.StatusNotFound) | ||||
| @@ -71,7 +91,8 @@ func TestAccessHandlerDeny(t *testing.T) { | ||||
| 	r.RemoteAddr = "1.2.3.4:4321" | ||||
| 	w := httptest.NewRecorder() | ||||
|  | ||||
| 	setting.allowedIPs = []net.IP{net.ParseIP("4.3.2.1")} | ||||
| 	_, netip, _ := net.ParseCIDR("4.3.2.1/32") | ||||
| 	setting.allowedNets = []*net.IPNet{netip} | ||||
|  | ||||
| 	wrappedHandler.ServeHTTP(w, r) | ||||
| 	assert.Equal(t, w.Code, http.StatusInternalServerError) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import ( | ||||
| type viperSettingType struct { | ||||
| 	BirdSocket      string `mapstructure:"bird_socket"` | ||||
| 	Listen          string `mapstructure:"listen"` | ||||
| 	AllowedIPs      string `mapstructure:"allowed_ips"` | ||||
| 	AllowedNets     string `mapstructure:"allowed_ips"` | ||||
| 	TracerouteBin   string `mapstructure:"traceroute_bin"` | ||||
| 	TracerouteFlags string `mapstructure:"traceroute_flags"` | ||||
| 	TracerouteRaw   bool   `mapstructure:"traceroute_raw"` | ||||
| @@ -40,7 +40,7 @@ func parseSettings() { | ||||
| 	pflag.String("listen", "8000", "listen address, set either in parameter or environment variable BIRDLG_PROXY_PORT") | ||||
| 	viper.BindPFlag("listen", pflag.Lookup("listen")) | ||||
|  | ||||
| 	pflag.String("allowed", "", "IPs allowed to access this proxy, separated by commas. Don't set to allow all IPs.") | ||||
| 	pflag.String("allowed", "", "IPs or networks allowed to access this proxy, separated by commas. Don't set to allow all IPs.") | ||||
| 	viper.BindPFlag("allowed_ips", pflag.Lookup("allowed")) | ||||
|  | ||||
| 	pflag.String("traceroute_bin", "", "traceroute binary file, set either in parameter or environment variable BIRDLG_TRACEROUTE_BIN") | ||||
| @@ -66,18 +66,31 @@ func parseSettings() { | ||||
| 	setting.birdSocket = viperSettings.BirdSocket | ||||
| 	setting.listen = viperSettings.Listen | ||||
|  | ||||
| 	if viperSettings.AllowedIPs != "" { | ||||
| 		for _, ip := range strings.Split(viperSettings.AllowedIPs, ",") { | ||||
| 			ipObject := net.ParseIP(ip) | ||||
| 			if ipObject == nil { | ||||
| 				fmt.Printf("Parse IP %s failed\n", ip) | ||||
| 				continue | ||||
| 	if viperSettings.AllowedNets != "" { | ||||
| 		for _, arg := range strings.Split(viperSettings.AllowedNets, ",") { | ||||
|  | ||||
| 			// if argument is an IP address, convert to CIDR by adding a suitable mask | ||||
| 			if !strings.Contains(arg, "/") { | ||||
| 				if strings.Contains(arg, ":") { | ||||
| 					// IPv6 address with /128 mask | ||||
| 					arg += "/128" | ||||
| 				} else { | ||||
| 					// IPv4 address with /32 mask | ||||
| 					arg += "/32" | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			setting.allowedIPs = append(setting.allowedIPs, ipObject) | ||||
| 			// parse the network | ||||
| 			_, netip, err := net.ParseCIDR(arg) | ||||
| 			if err != nil { | ||||
| 				fmt.Printf("Failed to parse CIDR %s: %s\n", arg, err.Error()) | ||||
| 				continue | ||||
| 			} | ||||
| 			setting.allowedNets = append(setting.allowedNets, netip) | ||||
|  | ||||
| 		} | ||||
| 	} else { | ||||
| 		setting.allowedIPs = []net.IP{} | ||||
| 		setting.allowedNets = []*net.IPNet{} | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
|   | ||||
		Reference in New Issue
	
	Block a user