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
	
		
			44 Commits
		
	
	
		
			lantian-de
			...
			v1.3.7.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 01438edaef | ||
|   | 90f36610dc | ||
|   | 6174208d07 | ||
|   | 76174cdc08 | ||
|   | 088bb6fe5a | ||
|   | 3951eed011 | ||
|   | 91c0a8962b | ||
|   | 5f7850a903 | ||
|   | 6a78cf2e80 | ||
|   | 5b5a44bcb6 | ||
|   | ac31862237 | ||
|   | 86129190ab | ||
|   | ff55064a20 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | dbb02c04ed | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c2b7de2e17 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c1b578e8db | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 7b0e5689d4 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 3c46bda49d | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 32e00d2ce3 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a19750cdef | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 7f1cdaa4ee | ||
|   | 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 | 
							
								
								
									
										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 }} | ||||
							
								
								
									
										23
									
								
								.github/workflows/develop.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/develop.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - '**' | ||||
|       - 'master' | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - 'master' | ||||
| @@ -47,7 +47,7 @@ jobs: | ||||
|       - 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 -I 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 | ||||
|  | ||||
| @@ -57,6 +57,12 @@ jobs: | ||||
|           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 | ||||
|  | ||||
|       - name: Test mtr binary in proxy image | ||||
|         run: | | ||||
|           docker build -t local/proxy:mtr -f proxy/Dockerfile.mtr proxy/ | ||||
|           docker run --rm --net host --entrypoint mtr local/proxy:mtr -w -c1 -Z1 -G1 -b 127.0.0.1 || exit 1 | ||||
|           docker run --rm --net host --entrypoint mtr local/proxy:mtr -w -c1 -Z1 -G1 -b ::1 || exit 1 | ||||
|  | ||||
|   docker-develop: | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: | ||||
| @@ -106,3 +112,16 @@ jobs: | ||||
|             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 }} | ||||
|  | ||||
|       - name: Build proxy docker image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           context: '{{defaultContext}}:proxy' | ||||
|           file: 'Dockerfile.mtr' | ||||
|           platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|           push: true | ||||
|           tags: | | ||||
|             xddxdd/bird-lgproxy-go:develop-mtr | ||||
|             xddxdd/bird-lgproxy-go:develop-${{ github.sha }}-mtr | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-develop-mtr | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-develop-${{ github.sha }}-mtr | ||||
|   | ||||
							
								
								
									
										22
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/release.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -7,6 +7,7 @@ jobs: | ||||
|     name: Release Go Binary | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         goos: [linux, windows, darwin] | ||||
|         goarch: ["386", amd64, "arm", arm64] | ||||
| @@ -22,7 +23,7 @@ jobs: | ||||
|       uses: actions/checkout@v3 | ||||
|  | ||||
|     - name: Release frontend | ||||
|       uses: wangyoucao577/go-release-action@v1.34 | ||||
|       uses: wangyoucao577/go-release-action@v1.40 | ||||
|       with: | ||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|         goos: ${{ matrix.goos }} | ||||
| @@ -31,7 +32,7 @@ jobs: | ||||
|         binary_name: "bird-lg-go" | ||||
|  | ||||
|     - name: Release proxy | ||||
|       uses: wangyoucao577/go-release-action@v1.34 | ||||
|       uses: wangyoucao577/go-release-action@v1.40 | ||||
|       with: | ||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||
|         goos: ${{ matrix.goos }} | ||||
| @@ -69,7 +70,9 @@ jobs: | ||||
|           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 | ||||
| @@ -79,4 +82,19 @@ jobs: | ||||
|           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 }} | ||||
|  | ||||
|       - name: Build proxy docker image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           context: '{{defaultContext}}:proxy' | ||||
|           file: 'Dockerfile.mtr' | ||||
|           platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7 | ||||
|           push: true | ||||
|           tags: | | ||||
|             xddxdd/bird-lgproxy-go:latest-mtr | ||||
|             xddxdd/bird-lgproxy-go:${{ github.event.release.tag_name }}-mtr | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-mtr | ||||
|             ghcr.io/xddxdd/bird-lg-go:proxy-${{ github.event.release.tag_name }}-mtr | ||||
|   | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -20,7 +20,3 @@ proxy/proxy | ||||
|  | ||||
| # don't include generated bindata file | ||||
| frontend/bindata.go | ||||
|  | ||||
| # don't include generated Dockerfiles | ||||
| frontend/Dockerfile.* | ||||
| proxy/Dockerfile.* | ||||
| @@ -125,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 | | ||||
| @@ -167,6 +167,7 @@ Example: the following docker-compose.yml entry does the same as above, but by s | ||||
| services: | ||||
|   bird-lgproxy: | ||||
|     # Use xddxdd/bird-lgproxy-go:develop for the latest build from master branch | ||||
|     # Use xddxdd/bird-lgproxy-go:latest-mtr to use MTR instead of Traceroute | ||||
|     image: xddxdd/bird-lgproxy-go:latest | ||||
|     container_name: bird-lgproxy | ||||
|     restart: always | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -4,26 +4,30 @@ 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/jarcoal/httpmock v1.3.1 | ||||
| 	github.com/magiconair/properties v1.8.7 | ||||
| 	github.com/spf13/pflag v1.0.5 | ||||
| 	github.com/spf13/viper v1.16.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/mitchellh/mapstructure v1.5.0 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.0.8 // indirect | ||||
| 	github.com/spf13/afero v1.9.5 // indirect | ||||
| 	github.com/spf13/cast v1.5.1 // indirect | ||||
| 	github.com/spf13/jwalterweatherman v1.1.0 // indirect | ||||
| 	github.com/subosito/gotenv v1.4.2 // indirect | ||||
| 	golang.org/x/sys v0.8.0 // indirect | ||||
| 	golang.org/x/text v0.9.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 | ||||
| ) | ||||
|   | ||||
							
								
								
									
										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 ( | ||||
| 	"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 | ||||
|   | ||||
| @@ -193,6 +193,11 @@ func summaryParse(data string, serverName string) (TemplateSummary, error) { | ||||
| 			row.Info = strings.TrimSpace(lineSplitted[10]) | ||||
| 		} | ||||
|  | ||||
| 		// Dynamic BGP session, show without any color | ||||
| 		if strings.Contains(row.Info, "Passive") { | ||||
| 			row.MappedState = summaryStateMap["passive"] | ||||
| 		} | ||||
|  | ||||
| 		// add to the result | ||||
| 		args.Rows = append(args.Rows, row) | ||||
| 	} | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
|   | ||||
							
								
								
									
										31
									
								
								proxy/Dockerfile.mtr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								proxy/Dockerfile.mtr
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| FROM golang AS step_0 | ||||
|  | ||||
| ENV CGO_ENABLED=0 GO111MODULE=on | ||||
| WORKDIR /root | ||||
| COPY . . | ||||
| RUN go build -ldflags "-w -s" -o /proxy | ||||
|  | ||||
| ################################################################################ | ||||
|  | ||||
| FROM alpine:edge AS step_1 | ||||
|  | ||||
| WORKDIR /root | ||||
| RUN apk add --no-cache build-base linux-headers | ||||
|  | ||||
| RUN wget https://www.bitwizard.nl/mtr/files/mtr-0.94.tar.gz \ | ||||
|     -O mtr-0.94.tar.gz | ||||
| RUN tar xvf mtr-0.94.tar.gz \ | ||||
|     && cd mtr-0.94 \ | ||||
|     && ./configure --without-gtk --without-ncurses --without-jansson --without-ipinfo --disable-bash-completion \ | ||||
|     && make -j4 LDFLAGS="-static" \ | ||||
|     && strip /root/mtr-0.94/mtr \ | ||||
|     && strip /root/mtr-0.94/mtr-packet | ||||
|  | ||||
| ################################################################################ | ||||
|  | ||||
| FROM scratch AS step_2 | ||||
| ENV PATH=/ | ||||
| COPY --from=step_0 /proxy / | ||||
| COPY --from=step_1 /root/mtr-0.94/mtr / | ||||
| COPY --from=step_1 /root/mtr-0.94/mtr-packet / | ||||
| ENTRYPOINT ["/proxy"] | ||||
							
								
								
									
										26
									
								
								proxy/go.mod
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								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.16.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/mitchellh/mapstructure v1.5.0 // indirect | ||||
| 	github.com/pelletier/go-toml/v2 v2.0.8 // indirect | ||||
| 	github.com/spf13/afero v1.9.5 // indirect | ||||
| 	github.com/spf13/cast v1.5.1 // indirect | ||||
| 	github.com/spf13/jwalterweatherman v1.1.0 // indirect | ||||
| 	github.com/subosito/gotenv v1.4.2 // indirect | ||||
| 	golang.org/x/sys v0.8.0 // indirect | ||||
| 	golang.org/x/text v0.9.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 | ||||
| ) | ||||
|   | ||||
							
								
								
									
										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 { | ||||
| 	// 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