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
	
		
			70 Commits
		
	
	
		
			lantian-de
			...
			v1.3.9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					1b2573d87c | ||
| 
						 | 
					0d5337508b | ||
| 
						 | 
					b9094d3d6c | ||
| 
						 | 
					ec7f348418 | ||
| 
						 | 
					a632739443 | ||
| 
						 | 
					a9e278357a | ||
| 
						 | 
					e4c00c897f | ||
| 
						 | 
					4df3918b35 | ||
| 
						 | 
					45dc24470d | ||
| 
						 | 
					55ea5c3b28 | ||
| 
						 | 
					7eb44c3828 | ||
| 
						 | 
					124fdedbda | ||
| 
						 | 
					e6a98358b5 | ||
| 
						 | 
					761eb2160a | ||
| 
						 | 
					cc2a146a88 | ||
| 
						 | 
					3db9454350 | ||
| 
						 | 
					c30bed112c | ||
| 
						 | 
					af5ab3c78f | ||
| 
						 | 
					0fdde8afc7 | ||
| 
						 | 
					39a129db9d | ||
| 
						 | 
					0dd1c07b66 | ||
| 
						 | 
					f0f072c4a6 | ||
| 
						 | 
					657565857b | ||
| 
						 | 
					7ac2158e70 | ||
| 
						 | 
					5c433bc27a | ||
| 
						 | 
					1b0b923da9 | ||
| 
						 | 
					01438edaef | ||
| 
						 | 
					90f36610dc | ||
| 
						 | 
					6174208d07 | ||
| 
						 | 
					76174cdc08 | ||
| 
						 | 
					088bb6fe5a | ||
| 
						 | 
					3951eed011 | ||
| 
						 | 
					91c0a8962b | ||
| 
						 | 
					5f7850a903 | ||
| 
						 | 
					6a78cf2e80 | ||
| 
						 | 
					5b5a44bcb6 | ||
| 
						 | 
					ac31862237 | ||
| 
						 | 
					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 | 
							
								
								
									
										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
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ type apiGenericResultPair struct {
 | 
			
		||||
type apiSummaryResultPair struct {
 | 
			
		||||
	Server string           `json:"server"`
 | 
			
		||||
	Data   []SummaryRowData `json:"data"`
 | 
			
		||||
	Error  string           `json:"error,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type apiResponse struct {
 | 
			
		||||
@@ -70,9 +71,12 @@ func apiSummaryHandler(request apiRequest) apiResponse {
 | 
			
		||||
	for i, result := range results {
 | 
			
		||||
		parsedSummary, err := summaryParse(result, request.Servers[i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return apiResponse{
 | 
			
		||||
				Error: err.Error(),
 | 
			
		||||
			}
 | 
			
		||||
			response.Result = append(response.Result, &apiSummaryResultPair{
 | 
			
		||||
				Server: request.Servers[i],
 | 
			
		||||
				Data:   []SummaryRowData{},
 | 
			
		||||
				Error:  err.Error(),
 | 
			
		||||
			})
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		response.Result = append(response.Result, &apiSummaryResultPair{
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,10 @@ func TestApiSummaryHandlerError(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	response := apiSummaryHandler(request)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, response.Error, "Mock backend error")
 | 
			
		||||
	assert.Equal(t, response.Error, "")
 | 
			
		||||
 | 
			
		||||
	summary := response.Result[0].(*apiSummaryResultPair)
 | 
			
		||||
	assert.Equal(t, summary.Error, "Mock backend error")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestApiWhoisHandler(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,19 @@
 | 
			
		||||
<script src="/static/jsdelivr/npm/viz.js@2.1.2/viz.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
<script src="/static/jsdelivr/npm/viz.js@2.1.2/lite.render.js" crossorigin="anonymous"></script>
 | 
			
		||||
<script>
 | 
			
		||||
  function decodeBase64(base64) {
 | 
			
		||||
    const text = atob(base64);
 | 
			
		||||
    const length = text.length;
 | 
			
		||||
    const bytes = new Uint8Array(length);
 | 
			
		||||
    for (let i = 0; i < length; i++) {
 | 
			
		||||
        bytes[i] = text.charCodeAt(i);
 | 
			
		||||
    }
 | 
			
		||||
    const decoder = new TextDecoder();
 | 
			
		||||
    return decoder.decode(bytes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var viz = new Viz();
 | 
			
		||||
  viz.renderSVGElement(atob({{ .Result }}))
 | 
			
		||||
  viz.renderSVGElement(decodeBase64({{ .Result }}))
 | 
			
		||||
  .then(element => {
 | 
			
		||||
    document.getElementById("bgpmap").appendChild(element);
 | 
			
		||||
  })
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,20 @@
 | 
			
		||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 | 
			
		||||
<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">
 | 
			
		||||
<link rel="stylesheet" href="/static/jsdelivr/npm/bootstrap@4.5.1/dist/css/bootstrap.min.css" 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>
 | 
			
		||||
@@ -74,8 +87,8 @@
 | 
			
		||||
	{{ .Content }}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script src="/static/jsdelivr/npm/jquery@3.5.1/dist/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
 | 
			
		||||
<script src="/static/jsdelivr/npm/bootstrap@4.5.1/dist/js/bootstrap.min.js" integrity="sha256-0IiaoZCI++9oAAvmCb5Y0r93XkuhvJpRalZLffQXLok=" crossorigin="anonymous"></script>
 | 
			
		||||
<script src="/static/jsdelivr/npm/jquery@3.5.1/dist/jquery.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
<script src="/static/jsdelivr/npm/bootstrap@4.5.1/dist/js/bootstrap.min.js" crossorigin="anonymous"></script>
 | 
			
		||||
<script src="/static/sortTable.js"></script>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -69,11 +70,15 @@ func (graph *RouteGraph) attrsToString(attrs RouteAttrs) string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (graph *RouteGraph) escape(s string) string {
 | 
			
		||||
	result, err := json.Marshal(s)
 | 
			
		||||
	buffer := &bytes.Buffer{}
 | 
			
		||||
	encoder := json.NewEncoder(buffer)
 | 
			
		||||
	encoder.SetEscapeHTML(false)
 | 
			
		||||
	err := encoder.Encode(s)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err.Error()
 | 
			
		||||
	} else {
 | 
			
		||||
		return string(result)
 | 
			
		||||
		return string(buffer.Bytes())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ func TestBirdRouteToGraphvizXSS(t *testing.T) {
 | 
			
		||||
		fakeResult,
 | 
			
		||||
	}, fakeResult)
 | 
			
		||||
 | 
			
		||||
	if strings.Contains(result, "<script>") {
 | 
			
		||||
	if strings.Contains(result, fakeResult) {
 | 
			
		||||
		t.Errorf("XSS injection succeeded: %s", result)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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/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/gorilla/handlers v1.5.2
 | 
			
		||||
	github.com/jarcoal/httpmock v1.4.0
 | 
			
		||||
	github.com/magiconair/properties v1.8.10
 | 
			
		||||
	github.com/spf13/pflag v1.0.6
 | 
			
		||||
	github.com/spf13/viper v1.19.0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/felixge/httpsnoop v1.0.3 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.6.0 // indirect
 | 
			
		||||
	github.com/felixge/httpsnoop v1.0.4 // 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.2.2 // 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.18.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
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1206
									
								
								frontend/go.sum
									
									
									
									
									
								
							
							
						
						
									
										1206
									
								
								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,26 @@ 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
 | 
			
		||||
	trustProxyHeaders bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,25 @@ 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"`
 | 
			
		||||
	TrustProxyHeaders bool   `mapstructure:"trust_proxy_headers"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse settings with viper, and convert to legacy setting format
 | 
			
		||||
@@ -87,9 +89,15 @@ 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.Bool("trust-proxy-headers", false, "Trust X-Forwared-For, X-Real-IP, X-Forwarded-Proto, X-Forwarded-Scheme and X-Forwarded-Host sent by the client")
 | 
			
		||||
	viper.BindPFlag("trust_proxy_headers", pflag.Lookup("trust-proxy-headers"))
 | 
			
		||||
 | 
			
		||||
	pflag.Parse()
 | 
			
		||||
 | 
			
		||||
	if err := viper.ReadInConfig(); err != nil {
 | 
			
		||||
@@ -139,6 +147,8 @@ func parseSettings() {
 | 
			
		||||
 | 
			
		||||
	setting.nameFilter = viperSettings.NameFilter
 | 
			
		||||
	setting.timeOut = viperSettings.TimeOut
 | 
			
		||||
	setting.connectionTimeOut = viperSettings.ConnectionTimeOut
 | 
			
		||||
	setting.trustProxyHeaders = viperSettings.TrustProxyHeaders
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("%#v\n", setting)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,6 @@ func webHandlerWhois(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
// serve up results from bird
 | 
			
		||||
func webBackendCommunicator(endpoint string, command string) func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
	backendCommandPrimitive, commandPresent := primitiveMap[command]
 | 
			
		||||
	if !commandPresent {
 | 
			
		||||
		panic("invalid command: " + command)
 | 
			
		||||
@@ -195,7 +194,6 @@ func webHandlerBGPMap(endpoint string, command string) func(w http.ResponseWrite
 | 
			
		||||
 | 
			
		||||
// set up routing paths and start webserver
 | 
			
		||||
func webServerStart(l net.Listener) {
 | 
			
		||||
 | 
			
		||||
	// redirect main page to all server summary
 | 
			
		||||
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		http.Redirect(w, r, "/summary/"+url.PathEscape(strings.Join(setting.servers, "+")), 302)
 | 
			
		||||
@@ -239,5 +237,11 @@ func webServerStart(l net.Listener) {
 | 
			
		||||
	http.HandleFunc("/telegram/", webHandlerTelegramBot)
 | 
			
		||||
 | 
			
		||||
	// Start HTTP server
 | 
			
		||||
	http.Serve(l, handlers.LoggingHandler(os.Stdout, http.DefaultServeMux))
 | 
			
		||||
	var handler http.Handler
 | 
			
		||||
	handler = http.DefaultServeMux
 | 
			
		||||
	if setting.trustProxyHeaders {
 | 
			
		||||
		handler = handlers.ProxyHeaders(handler)
 | 
			
		||||
	}
 | 
			
		||||
	handler = handlers.LoggingHandler(os.Stdout, handler)
 | 
			
		||||
	http.Serve(l, handler)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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"]
 | 
			
		||||
							
								
								
									
										32
									
								
								proxy/go.mod
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								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/magiconair/properties v1.8.7
 | 
			
		||||
	github.com/spf13/pflag v1.0.5
 | 
			
		||||
	github.com/spf13/viper v1.16.0
 | 
			
		||||
	github.com/gorilla/handlers v1.5.2
 | 
			
		||||
	github.com/magiconair/properties v1.8.10
 | 
			
		||||
	github.com/spf13/pflag v1.0.6
 | 
			
		||||
	github.com/spf13/viper v1.19.0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/felixge/httpsnoop v1.0.3 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.6.0 // indirect
 | 
			
		||||
	github.com/felixge/httpsnoop v1.0.4 // 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.2.2 // 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.18.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
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1198
									
								
								proxy/go.sum
									
									
									
									
									
								
							
							
						
						
									
										1198
									
								
								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