You've already forked bird-lg-go
mirror of
https://github.com/xddxdd/bird-lg-go
synced 2025-10-14 19:42:16 +02:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
86129190ab | ||
![]() |
ff55064a20 | ||
![]() |
dbb02c04ed | ||
![]() |
c2b7de2e17 | ||
![]() |
c1b578e8db | ||
![]() |
7b0e5689d4 | ||
![]() |
3c46bda49d | ||
![]() |
32e00d2ce3 | ||
![]() |
a19750cdef | ||
![]() |
7f1cdaa4ee | ||
![]() |
2d2193041e | ||
![]() |
aad8ee98d7 | ||
![]() |
00b5c12787 | ||
![]() |
55a1eb54fd | ||
![]() |
0594edc69d | ||
![]() |
38bf6aba09 | ||
![]() |
d261c22235 | ||
![]() |
19aa8c77c5 | ||
![]() |
fe07ebb5a5 | ||
![]() |
66547ebfa9 | ||
![]() |
d253e4311b | ||
![]() |
026498ba2f | ||
![]() |
27c348a864 | ||
![]() |
43b4ad93dd | ||
![]() |
6176c45006 | ||
![]() |
47113184f4 | ||
![]() |
3c9a3e4339 | ||
![]() |
8457b18d46 | ||
![]() |
f8f64b03a6 | ||
![]() |
cc818c1cc0 | ||
![]() |
6224b43808 | ||
![]() |
17e0b14243 | ||
![]() |
b4c1bed9ba | ||
![]() |
abb32abff3 | ||
![]() |
b368c75aa3 | ||
![]() |
09405cdb38 | ||
![]() |
f999d47d9f | ||
![]() |
005dfb1435 | ||
![]() |
4bd7a6bb95 | ||
![]() |
462d76a2d0 | ||
![]() |
58f217578c | ||
![]() |
0e95727de1 | ||
![]() |
a48f1c8040 | ||
![]() |
81acde3a37 | ||
![]() |
7c0fe0d512 | ||
![]() |
a5f4452d02 | ||
![]() |
b237185ef7 | ||
![]() |
e949646790 | ||
![]() |
bb479d22ae | ||
![]() |
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"]
|
||||
|
@@ -8,6 +8,19 @@
|
||||
<meta name="renderer" content="webkit">
|
||||
<title>{{ html .Title }}</title>
|
||||
<link rel="stylesheet" href="/static/jsdelivr/npm/bootstrap@4.5.1/dist/css/bootstrap.min.css" integrity="sha256-VoFZSlmyTXsegReQCNmbXrS4hBBUl/cexZvPmPWoJsY=" crossorigin="anonymous">
|
||||
<style>
|
||||
.navbar-nav {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.navbar form {
|
||||
min-width: 400px;
|
||||
}
|
||||
.nav-link {
|
||||
padding: 0.2rem 0.5rem !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
</head>
|
||||
<body>
|
||||
@@ -60,7 +73,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.2
|
||||
)
|
||||
|
||||
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.2
|
||||
)
|
||||
|
||||
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