You've already forked bird-lg-go
mirror of
https://github.com/xddxdd/bird-lg-go
synced 2025-11-02 13:02:29 +01:00
Compare commits
23 Commits
lantian-de
...
v1.3.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d2193041e | ||
|
|
aad8ee98d7 | ||
|
|
00b5c12787 | ||
|
|
55a1eb54fd | ||
|
|
0594edc69d | ||
|
|
38bf6aba09 | ||
|
|
d261c22235 | ||
|
|
19aa8c77c5 | ||
|
|
fe07ebb5a5 | ||
|
|
66547ebfa9 | ||
|
|
d253e4311b | ||
|
|
026498ba2f | ||
|
|
27c348a864 | ||
|
|
43b4ad93dd | ||
|
|
6176c45006 | ||
|
|
47113184f4 | ||
|
|
3c9a3e4339 | ||
|
|
8457b18d46 | ||
|
|
f8f64b03a6 | ||
|
|
cc818c1cc0 | ||
|
|
6224b43808 | ||
|
|
17e0b14243 | ||
|
|
b4c1bed9ba |
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 }}
|
||||||
2
.github/workflows/develop.yaml
vendored
2
.github/workflows/develop.yaml
vendored
@@ -1,7 +1,7 @@
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- '**'
|
- 'master'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
|
|||||||
9
.github/workflows/release.yaml
vendored
9
.github/workflows/release.yaml
vendored
@@ -7,6 +7,7 @@ jobs:
|
|||||||
name: Release Go Binary
|
name: Release Go Binary
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
goos: [linux, windows, darwin]
|
goos: [linux, windows, darwin]
|
||||||
goarch: ["386", amd64, "arm", arm64]
|
goarch: ["386", amd64, "arm", arm64]
|
||||||
@@ -22,7 +23,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Release frontend
|
- name: Release frontend
|
||||||
uses: wangyoucao577/go-release-action@v1.34
|
uses: wangyoucao577/go-release-action@v1.40
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
goos: ${{ matrix.goos }}
|
goos: ${{ matrix.goos }}
|
||||||
@@ -31,7 +32,7 @@ jobs:
|
|||||||
binary_name: "bird-lg-go"
|
binary_name: "bird-lg-go"
|
||||||
|
|
||||||
- name: Release proxy
|
- name: Release proxy
|
||||||
uses: wangyoucao577/go-release-action@v1.34
|
uses: wangyoucao577/go-release-action@v1.40
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
goos: ${{ matrix.goos }}
|
goos: ${{ matrix.goos }}
|
||||||
@@ -69,7 +70,9 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
xddxdd/bird-lg-go:latest
|
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
|
||||||
|
ghcr.io/xddxdd/bird-lg-go:frontend-${{ github.event.release.tag_name }}
|
||||||
|
|
||||||
- name: Build proxy docker image
|
- name: Build proxy docker image
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
@@ -79,4 +82,6 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
xddxdd/bird-lgproxy-go:latest
|
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
|
||||||
|
ghcr.io/xddxdd/bird-lg-go:proxy-${{ github.event.release.tag_name }}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ Configuration is handled by [viper](https://github.com/spf13/viper), any config
|
|||||||
|
|
||||||
| Config Key | Parameter | Environment Variable | Description |
|
| 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") |
|
| 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") |
|
| 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 |
|
| traceroute_bin | --traceroute_bin | BIRDLG_TRACEROUTE_BIN | traceroute binary file, set either in parameter or environment variable BIRDLG_TRACEROUTE_BIN |
|
||||||
|
|||||||
@@ -4,26 +4,30 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
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/jarcoal/httpmock v1.3.1
|
github.com/jarcoal/httpmock v1.3.1
|
||||||
github.com/magiconair/properties v1.8.7
|
github.com/magiconair/properties v1.8.7
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.16.0
|
github.com/spf13/viper v1.18.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
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/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/spf13/afero v1.9.5 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/spf13/cast v1.5.1 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/subosito/gotenv v1.4.2 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // 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/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
830
frontend/go.sum
830
frontend/go.sum
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jarcoal/httpmock"
|
||||||
)
|
)
|
||||||
|
|
||||||
type channelData struct {
|
type channelData struct {
|
||||||
@@ -14,6 +17,29 @@ type channelData struct {
|
|||||||
data string
|
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
|
// Send commands to lgproxy instances in parallel, and retrieve their responses
|
||||||
func batchRequest(servers []string, endpoint string, command string) []string {
|
func batchRequest(servers []string, endpoint string, command string) []string {
|
||||||
// Channel and array for storing responses
|
// 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)
|
url := "http://" + hostname + ":" + strconv.Itoa(setting.proxyPort) + "/" + url.PathEscape(endpoint) + "?q=" + url.QueryEscape(command)
|
||||||
go func(url string, i int) {
|
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)
|
response, err := client.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- channelData{i, "request failed: " + err.Error() + "\n"}
|
ch <- channelData{i, "request failed: " + err.Error() + "\n"}
|
||||||
|
|||||||
@@ -7,24 +7,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type settingType struct {
|
type settingType struct {
|
||||||
servers []string
|
servers []string
|
||||||
serversDisplay []string
|
serversDisplay []string
|
||||||
domain string
|
domain string
|
||||||
proxyPort int
|
proxyPort int
|
||||||
whoisServer string
|
whoisServer string
|
||||||
listen string
|
listen string
|
||||||
dnsInterface string
|
dnsInterface string
|
||||||
netSpecificMode string
|
netSpecificMode string
|
||||||
titleBrand string
|
titleBrand string
|
||||||
navBarBrand string
|
navBarBrand string
|
||||||
navBarBrandURL string
|
navBarBrandURL string
|
||||||
navBarAllServer string
|
navBarAllServer string
|
||||||
navBarAllURL string
|
navBarAllURL string
|
||||||
bgpmapInfo string
|
bgpmapInfo string
|
||||||
telegramBotName string
|
telegramBotName string
|
||||||
protocolFilter []string
|
protocolFilter []string
|
||||||
nameFilter string
|
nameFilter string
|
||||||
timeOut int
|
timeOut int
|
||||||
|
connectionTimeOut int
|
||||||
}
|
}
|
||||||
|
|
||||||
var setting settingType
|
var setting settingType
|
||||||
|
|||||||
@@ -9,23 +9,24 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type viperSettingType struct {
|
type viperSettingType struct {
|
||||||
Servers string `mapstructure:"servers"`
|
Servers string `mapstructure:"servers"`
|
||||||
Domain string `mapstructure:"domain"`
|
Domain string `mapstructure:"domain"`
|
||||||
ProxyPort int `mapstructure:"proxy_port"`
|
ProxyPort int `mapstructure:"proxy_port"`
|
||||||
WhoisServer string `mapstructure:"whois"`
|
WhoisServer string `mapstructure:"whois"`
|
||||||
Listen string `mapstructure:"listen"`
|
Listen string `mapstructure:"listen"`
|
||||||
DNSInterface string `mapstructure:"dns_interface"`
|
DNSInterface string `mapstructure:"dns_interface"`
|
||||||
NetSpecificMode string `mapstructure:"net_specific_mode"`
|
NetSpecificMode string `mapstructure:"net_specific_mode"`
|
||||||
TitleBrand string `mapstructure:"title_brand"`
|
TitleBrand string `mapstructure:"title_brand"`
|
||||||
NavBarBrand string `mapstructure:"navbar_brand"`
|
NavBarBrand string `mapstructure:"navbar_brand"`
|
||||||
NavBarBrandURL string `mapstructure:"navbar_brand_url"`
|
NavBarBrandURL string `mapstructure:"navbar_brand_url"`
|
||||||
NavBarAllServer string `mapstructure:"navbar_all_servers"`
|
NavBarAllServer string `mapstructure:"navbar_all_servers"`
|
||||||
NavBarAllURL string `mapstructure:"navbar_all_url"`
|
NavBarAllURL string `mapstructure:"navbar_all_url"`
|
||||||
BgpmapInfo string `mapstructure:"bgpmap_info"`
|
BgpmapInfo string `mapstructure:"bgpmap_info"`
|
||||||
TelegramBotName string `mapstructure:"telegram_bot_name"`
|
TelegramBotName string `mapstructure:"telegram_bot_name"`
|
||||||
ProtocolFilter string `mapstructure:"protocol_filter"`
|
ProtocolFilter string `mapstructure:"protocol_filter"`
|
||||||
NameFilter string `mapstructure:"name_filter"`
|
NameFilter string `mapstructure:"name_filter"`
|
||||||
TimeOut int `mapstructure:"timeout"`
|
TimeOut int `mapstructure:"timeout"`
|
||||||
|
ConnectionTimeOut int `mapstructure:"connection_timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse settings with viper, and convert to legacy setting format
|
// 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")
|
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"))
|
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"))
|
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()
|
pflag.Parse()
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
@@ -139,6 +143,7 @@ func parseSettings() {
|
|||||||
|
|
||||||
setting.nameFilter = viperSettings.NameFilter
|
setting.nameFilter = viperSettings.NameFilter
|
||||||
setting.timeOut = viperSettings.TimeOut
|
setting.timeOut = viperSettings.TimeOut
|
||||||
|
setting.connectionTimeOut = viperSettings.ConnectionTimeOut
|
||||||
|
|
||||||
fmt.Printf("%#v\n", setting)
|
fmt.Printf("%#v\n", setting)
|
||||||
}
|
}
|
||||||
|
|||||||
26
proxy/go.mod
26
proxy/go.mod
@@ -4,25 +4,29 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
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/magiconair/properties v1.8.7
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.16.0
|
github.com/spf13/viper v1.18.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
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/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/spf13/afero v1.9.5 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/spf13/cast v1.5.1 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/subosito/gotenv v1.4.2 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // 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/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
830
proxy/go.sum
830
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 {
|
func hasAccess(remoteAddr string) bool {
|
||||||
// setting.allowedIPs will always have at least one element because of how it's defined
|
// setting.allowedNets will always have at least one element because of how it's defined
|
||||||
if len(setting.allowedIPs) == 0 {
|
if len(setting.allowedNets) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ func hasAccess(remoteAddr string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, allowedIP := range setting.allowedIPs {
|
for _, net := range setting.allowedNets {
|
||||||
if ipObject.Equal(allowedIP) {
|
if net.Contains(ipObject) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ func hasAccess(remoteAddr string) bool {
|
|||||||
return false
|
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 {
|
func accessHandler(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(httpW http.ResponseWriter, httpR *http.Request) {
|
return http.HandlerFunc(func(httpW http.ResponseWriter, httpR *http.Request) {
|
||||||
if hasAccess(httpR.RemoteAddr) {
|
if hasAccess(httpR.RemoteAddr) {
|
||||||
@@ -61,12 +61,12 @@ func accessHandler(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type settingType struct {
|
type settingType struct {
|
||||||
birdSocket string
|
birdSocket string
|
||||||
listen string
|
listen string
|
||||||
allowedIPs []net.IP
|
allowedNets []*net.IPNet
|
||||||
tr_bin string
|
tr_bin string
|
||||||
tr_flags []string
|
tr_flags []string
|
||||||
tr_raw bool
|
tr_raw bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var setting settingType
|
var setting settingType
|
||||||
|
|||||||
@@ -10,42 +10,61 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestHasAccessNotConfigured(t *testing.T) {
|
func TestHasAccessNotConfigured(t *testing.T) {
|
||||||
setting.allowedIPs = []net.IP{}
|
setting.allowedNets = []*net.IPNet{}
|
||||||
assert.Equal(t, hasAccess("whatever"), true)
|
assert.Equal(t, hasAccess("whatever"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessAllowIPv4(t *testing.T) {
|
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)
|
assert.Equal(t, hasAccess("1.2.3.4:4321"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessDenyIPv4(t *testing.T) {
|
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)
|
assert.Equal(t, hasAccess("1.2.3.4:4321"), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessAllowIPv6(t *testing.T) {
|
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)
|
assert.Equal(t, hasAccess("[2001:db8::1]:4321"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessAllowIPv6DifferentForm(t *testing.T) {
|
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)
|
assert.Equal(t, hasAccess("[2001:db8::1]:4321"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessDenyIPv6(t *testing.T) {
|
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)
|
assert.Equal(t, hasAccess("[2001:db8::1]:4321"), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessBadClientIP(t *testing.T) {
|
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)
|
assert.Equal(t, hasAccess("not an IP"), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasAccessBadClientIPPort(t *testing.T) {
|
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)
|
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"
|
r.RemoteAddr = "1.2.3.4:4321"
|
||||||
w := httptest.NewRecorder()
|
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)
|
wrappedHandler.ServeHTTP(w, r)
|
||||||
assert.Equal(t, w.Code, http.StatusNotFound)
|
assert.Equal(t, w.Code, http.StatusNotFound)
|
||||||
@@ -71,7 +91,8 @@ func TestAccessHandlerDeny(t *testing.T) {
|
|||||||
r.RemoteAddr = "1.2.3.4:4321"
|
r.RemoteAddr = "1.2.3.4:4321"
|
||||||
w := httptest.NewRecorder()
|
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)
|
wrappedHandler.ServeHTTP(w, r)
|
||||||
assert.Equal(t, w.Code, http.StatusInternalServerError)
|
assert.Equal(t, w.Code, http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
type viperSettingType struct {
|
type viperSettingType struct {
|
||||||
BirdSocket string `mapstructure:"bird_socket"`
|
BirdSocket string `mapstructure:"bird_socket"`
|
||||||
Listen string `mapstructure:"listen"`
|
Listen string `mapstructure:"listen"`
|
||||||
AllowedIPs string `mapstructure:"allowed_ips"`
|
AllowedNets string `mapstructure:"allowed_ips"`
|
||||||
TracerouteBin string `mapstructure:"traceroute_bin"`
|
TracerouteBin string `mapstructure:"traceroute_bin"`
|
||||||
TracerouteFlags string `mapstructure:"traceroute_flags"`
|
TracerouteFlags string `mapstructure:"traceroute_flags"`
|
||||||
TracerouteRaw bool `mapstructure:"traceroute_raw"`
|
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")
|
pflag.String("listen", "8000", "listen address, set either in parameter or environment variable BIRDLG_PROXY_PORT")
|
||||||
viper.BindPFlag("listen", pflag.Lookup("listen"))
|
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"))
|
viper.BindPFlag("allowed_ips", pflag.Lookup("allowed"))
|
||||||
|
|
||||||
pflag.String("traceroute_bin", "", "traceroute binary file, set either in parameter or environment variable BIRDLG_TRACEROUTE_BIN")
|
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.birdSocket = viperSettings.BirdSocket
|
||||||
setting.listen = viperSettings.Listen
|
setting.listen = viperSettings.Listen
|
||||||
|
|
||||||
if viperSettings.AllowedIPs != "" {
|
if viperSettings.AllowedNets != "" {
|
||||||
for _, ip := range strings.Split(viperSettings.AllowedIPs, ",") {
|
for _, arg := range strings.Split(viperSettings.AllowedNets, ",") {
|
||||||
ipObject := net.ParseIP(ip)
|
|
||||||
if ipObject == nil {
|
// if argument is an IP address, convert to CIDR by adding a suitable mask
|
||||||
fmt.Printf("Parse IP %s failed\n", ip)
|
if !strings.Contains(arg, "/") {
|
||||||
continue
|
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 {
|
} else {
|
||||||
setting.allowedIPs = []net.IP{}
|
setting.allowedNets = []*net.IPNet{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
Reference in New Issue
Block a user