1
mirror of https://github.com/xddxdd/bird-lg-go synced 2025-10-14 19:42:16 +02:00

157 Commits

Author SHA1 Message Date
Lan Tian
1b2573d87c release: v1.3.9 2025-04-23 21:13:36 -07:00
Lan Tian
0d5337508b frontend: update API test to adapt to changes in #118 2025-04-23 21:12:40 -07:00
Mxmilu666
b9094d3d6c fix(template): typo 2025-04-23 21:08:40 -07:00
Mxmilu666
ec7f348418 feat(api): return data from available services even if one backend fails 2025-04-23 21:08:40 -07:00
dependabot[bot]
a632739443 Merge pull request #117 from xddxdd/dependabot/go_modules/proxy/github.com/magiconair/properties-1.8.10 2025-04-10 00:55:19 +00:00
dependabot[bot]
a9e278357a build(deps): bump github.com/magiconair/properties in /proxy
Bumps [github.com/magiconair/properties](https://github.com/magiconair/properties) from 1.8.9 to 1.8.10.
- [Release notes](https://github.com/magiconair/properties/releases)
- [Commits](https://github.com/magiconair/properties/compare/v1.8.9...v1.8.10)

---
updated-dependencies:
- dependency-name: github.com/magiconair/properties
  dependency-version: 1.8.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-10 00:53:10 +00:00
dependabot[bot]
e4c00c897f Merge pull request #116 from xddxdd/dependabot/go_modules/frontend/github.com/magiconair/properties-1.8.10 2025-04-10 00:22:47 +00:00
dependabot[bot]
4df3918b35 build(deps): bump github.com/magiconair/properties in /frontend
Bumps [github.com/magiconair/properties](https://github.com/magiconair/properties) from 1.8.9 to 1.8.10.
- [Release notes](https://github.com/magiconair/properties/releases)
- [Commits](https://github.com/magiconair/properties/compare/v1.8.9...v1.8.10)

---
updated-dependencies:
- dependency-name: github.com/magiconair/properties
  dependency-version: 1.8.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-10 00:20:55 +00:00
dependabot[bot]
45dc24470d Merge pull request #115 from xddxdd/dependabot/go_modules/frontend/github.com/jarcoal/httpmock-1.4.0 2025-04-07 00:54:10 +00:00
dependabot[bot]
55ea5c3b28 build(deps): bump github.com/jarcoal/httpmock in /frontend
Bumps [github.com/jarcoal/httpmock](https://github.com/jarcoal/httpmock) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/jarcoal/httpmock/releases)
- [Commits](https://github.com/jarcoal/httpmock/compare/v1.3.1...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/jarcoal/httpmock
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 00:52:24 +00:00
dependabot[bot]
7eb44c3828 Merge pull request #110 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/pflag-1.0.6 2025-01-30 00:16:58 +00:00
dependabot[bot]
124fdedbda build(deps): bump github.com/spf13/pflag from 1.0.5 to 1.0.6 in /proxy
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.5...v1.0.6)

---
updated-dependencies:
- dependency-name: github.com/spf13/pflag
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-30 00:14:41 +00:00
dependabot[bot]
e6a98358b5 Merge pull request #109 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/pflag-1.0.6 2025-01-30 00:04:45 +00:00
dependabot[bot]
761eb2160a build(deps): bump github.com/spf13/pflag in /frontend
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.5...v1.0.6)

---
updated-dependencies:
- dependency-name: github.com/spf13/pflag
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-30 00:02:32 +00:00
dependabot[bot]
cc2a146a88 Merge pull request #108 from xddxdd/dependabot/go_modules/frontend/github.com/magiconair/properties-1.8.9 2024-12-09 00:51:25 +00:00
dependabot[bot]
3db9454350 build(deps): bump github.com/magiconair/properties in /frontend
Bumps [github.com/magiconair/properties](https://github.com/magiconair/properties) from 1.8.7 to 1.8.9.
- [Release notes](https://github.com/magiconair/properties/releases)
- [Commits](https://github.com/magiconair/properties/compare/v1.8.7...v1.8.9)

---
updated-dependencies:
- dependency-name: github.com/magiconair/properties
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 00:50:06 +00:00
dependabot[bot]
c30bed112c Merge pull request #107 from xddxdd/dependabot/go_modules/proxy/github.com/magiconair/properties-1.8.9 2024-12-09 00:18:14 +00:00
dependabot[bot]
af5ab3c78f build(deps): bump github.com/magiconair/properties in /proxy
Bumps [github.com/magiconair/properties](https://github.com/magiconair/properties) from 1.8.7 to 1.8.9.
- [Release notes](https://github.com/magiconair/properties/releases)
- [Commits](https://github.com/magiconair/properties/compare/v1.8.7...v1.8.9)

---
updated-dependencies:
- dependency-name: github.com/magiconair/properties
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 00:16:23 +00:00
Marc 'risson' Schmitt
0fdde8afc7 frontend: allow webserver to trust proxy headers (#106)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-07-14 15:50:18 -07:00
Lan Tian
39a129db9d release: v1.3.8 2024-07-01 21:31:55 -07:00
Lan Tian
0dd1c07b66 frontend: disable escaping of special HTML chars for BGPMap graph 2024-07-01 21:17:43 -07:00
Lan Tian
f0f072c4a6 frontend: handle UTF-8 characters in GraphViz graphs 2024-06-30 13:04:15 -07:00
dependabot[bot]
657565857b Merge pull request #104 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/viper-1.19.0 2024-06-03 00:40:25 +00:00
dependabot[bot]
7ac2158e70 build(deps): bump github.com/spf13/viper from 1.18.2 to 1.19.0 in /proxy
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.2 to 1.19.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.2...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 00:38:37 +00:00
dependabot[bot]
5c433bc27a Merge pull request #103 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/viper-1.19.0 2024-06-03 00:35:26 +00:00
dependabot[bot]
1b0b923da9 build(deps): bump github.com/spf13/viper in /frontend
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.2 to 1.19.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.2...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-03 00:32:44 +00:00
Lan Tian
01438edaef release: v1.3.7.1 2024-03-12 18:05:50 -07:00
Lan Tian
90f36610dc ci: fix failing whois test 2024-03-12 18:03:23 -07:00
Lan Tian
6174208d07 ci: fix typo in release workflow 2024-03-12 17:56:52 -07:00
Lan Tian
76174cdc08 release: v1.3.7 2024-03-12 17:47:29 -07:00
Lan Tian
088bb6fe5a readme: add mention of MTR based lgproxy docker image 2024-03-12 17:46:56 -07:00
Lan Tian
3951eed011 ci: fix dockerfile path for proxy image with mtr 2024-03-09 12:21:00 -08:00
Lan Tian
91c0a8962b ci: also test mtr binary in proxy image 2024-03-09 12:09:19 -08:00
Lan Tian
5f7850a903 ci: also build docker image with mtr on regular commits 2024-03-09 12:05:20 -08:00
Lan Tian
6a78cf2e80 proxy: add docker image with mtr 2024-03-09 12:04:05 -08:00
Lan Tian
5b5a44bcb6 release: v1.3.6 2024-02-25 19:47:39 -08:00
Marc 'risson' Schmitt
ac31862237 frontend: show dynamic BGP sessions without any color (#98)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-02-18 22:11:20 -08:00
Lan Tian
86129190ab release: v1.3.5 2024-01-01 14:43:25 -08:00
Lan Tian
ff55064a20 frontend: adjust navbar display of many servers 2023-12-31 16:31:56 -08:00
dependabot[bot]
dbb02c04ed Merge pull request #95 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/viper-1.18.2 2023-12-19 00:50:09 +00:00
dependabot[bot]
c2b7de2e17 build(deps): bump github.com/spf13/viper from 1.18.1 to 1.18.2 in /proxy
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.1 to 1.18.2.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.1...v1.18.2)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 00:48:47 +00:00
dependabot[bot]
c1b578e8db Merge pull request #94 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/viper-1.18.2 2023-12-19 00:28:10 +00:00
dependabot[bot]
7b0e5689d4 build(deps): bump github.com/spf13/viper in /frontend
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.1 to 1.18.2.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.1...v1.18.2)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 00:26:13 +00:00
dependabot[bot]
3c46bda49d Merge pull request #93 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/viper-1.18.1 2023-12-11 00:45:58 +00:00
dependabot[bot]
32e00d2ce3 build(deps): bump github.com/spf13/viper in /frontend
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.0...v1.18.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 00:44:41 +00:00
dependabot[bot]
a19750cdef Merge pull request #92 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/viper-1.18.1 2023-12-11 00:04:27 +00:00
dependabot[bot]
7f1cdaa4ee build(deps): bump github.com/spf13/viper from 1.18.0 to 1.18.1 in /proxy
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.18.0...v1.18.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 00:03:09 +00:00
Lan Tian
2d2193041e release: v1.3.4 2023-12-06 23:54:47 -08:00
dependabot[bot]
aad8ee98d7 Merge pull request #91 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/viper-1.18.0 2023-12-07 00:58:49 +00:00
dependabot[bot]
00b5c12787 build(deps): bump github.com/spf13/viper in /frontend
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 00:57:01 +00:00
dependabot[bot]
55a1eb54fd Merge pull request #90 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/viper-1.18.0 2023-12-07 00:33:12 +00:00
dependabot[bot]
0594edc69d build(deps): bump github.com/spf13/viper from 1.17.0 to 1.18.0 in /proxy
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 00:31:37 +00:00
Lan Tian
38bf6aba09 frontend: fix unit tests 2023-11-25 10:47:37 -08:00
Lan Tian
d261c22235 frontend: add connection timeout 2023-11-25 10:30:13 -08:00
dependabot[bot]
19aa8c77c5 Merge pull request #88 from xddxdd/dependabot/go_modules/frontend/github.com/gorilla/handlers-1.5.2 2023-11-06 01:01:43 +00:00
dependabot[bot]
fe07ebb5a5 build(deps): bump github.com/gorilla/handlers in /frontend
Bumps [github.com/gorilla/handlers](https://github.com/gorilla/handlers) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/gorilla/handlers/releases)
- [Commits](https://github.com/gorilla/handlers/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/handlers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 01:00:08 +00:00
dependabot[bot]
66547ebfa9 Merge pull request #87 from xddxdd/dependabot/go_modules/proxy/github.com/gorilla/handlers-1.5.2 2023-11-06 00:24:24 +00:00
dependabot[bot]
d253e4311b build(deps): bump github.com/gorilla/handlers in /proxy
Bumps [github.com/gorilla/handlers](https://github.com/gorilla/handlers) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/gorilla/handlers/releases)
- [Commits](https://github.com/gorilla/handlers/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/handlers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 00:22:00 +00:00
Lan Tian
026498ba2f general: auto merge updates from dependabot 2023-10-24 23:32:55 -07:00
Lan Tian
27c348a864 release: v1.3.3 2023-10-21 00:03:02 -07:00
Lan Tian
43b4ad93dd general: only build docker develop images on master branch push 2023-10-08 21:08:07 -07:00
dependabot[bot]
6176c45006 build(deps): bump github.com/spf13/viper from 1.16.0 to 1.17.0 in /proxy (#86)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-08 21:04:12 -07:00
dependabot[bot]
47113184f4 build(deps): bump github.com/spf13/viper in /frontend (#85)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-08 21:04:04 -07:00
Simon Marsh
3c9a3e4339 Enable proxy to allow access by CIDR network as well as IP (#84) 2023-10-04 21:33:37 -07:00
Lan Tian
8457b18d46 release: v1.3.2.2 2023-09-09 01:44:16 -07:00
Lan Tian
f8f64b03a6 general: add tag for release Docker images 2023-09-09 01:42:38 -07:00
Lan Tian
cc818c1cc0 release: v1.3.2.1 2023-09-09 01:33:24 -07:00
Lan Tian
6224b43808 general: update GitHub actions 2023-09-09 01:32:56 -07:00
Lan Tian
17e0b14243 general: update GitHub actions 2023-09-09 01:29:49 -07:00
Lan Tian
b4c1bed9ba release: v1.3.2 2023-09-09 01:23:14 -07:00
Lan Tian
abb32abff3 general: add unit test for docker images 2023-09-08 18:45:58 -07:00
Lan Tian
b368c75aa3 frontend: fix whois client cannot get default whois port 2023-09-08 18:38:23 -07:00
Lan Tian
09405cdb38 frontend: also print whois client output on error 2023-09-08 18:22:31 -07:00
Lan Tian
f999d47d9f frontend: force enable whois client regex parser on alpine/musl 2023-09-07 19:14:04 -07:00
Lan Tian
005dfb1435 frontend: make docker image whois client try to use config file 2023-09-07 00:51:56 -07:00
Lan Tian
4bd7a6bb95 general: also release docker image to GitHub container registry 2023-09-06 21:06:10 -07:00
Lan Tian
462d76a2d0 general: reenable docker multiarch build 2023-09-06 21:02:32 -07:00
Lan Tian
58f217578c readme: add note about development version of docker image 2023-09-06 20:59:27 -07:00
Lan Tian
0e95727de1 general: reorganize GitHub Actions workflows and readd unit test 2023-09-06 20:55:45 -07:00
Lan Tian
a48f1c8040 general: move Docker image build to GitHub Actions 2023-09-06 20:48:14 -07:00
Lan Tian
81acde3a37 frontend: add whois client for more complex whois lookup 2023-09-06 20:35:30 -07:00
Lan Tian
7c0fe0d512 proxy: update traceroute version in Docker image 2023-09-06 20:33:40 -07:00
dependabot[bot]
a5f4452d02 build(deps): bump github.com/jarcoal/httpmock in /frontend (#82)
Bumps [github.com/jarcoal/httpmock](https://github.com/jarcoal/httpmock) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/jarcoal/httpmock/releases)
- [Commits](https://github.com/jarcoal/httpmock/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/jarcoal/httpmock
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-25 00:44:30 -07:00
Lan Tian
b237185ef7 release: v1.3.1 2023-06-18 20:14:41 -07:00
towalink
e949646790 Properly escape URL path (#81) 2023-06-10 15:14:10 -07:00
dependabot[bot]
bb479d22ae build(deps): bump github.com/spf13/viper from 1.15.0 to 1.16.0 in /proxy (#79)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-02 00:58:12 -07:00
dependabot[bot]
d40f41b4d5 build(deps): bump github.com/spf13/viper in /frontend (#80)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-02 00:58:06 -07:00
Lan Tian
cdc34704b5 release: v1.3.0 2023-05-14 12:37:46 -07:00
Lan Tian
db58bd3354 frontend: add a test case for lookup DNS -> WHOIS fallback 2023-05-06 00:26:40 -07:00
Lan Tian
a0246ccee2 general: add unit tests for >80% coverage
Includes a few minor fixes:
- frontend: support setting port for WHOIS server
- proxy: fix handling of very long lines
- proxy: refactor IP allowlist logic, parse allow IP list at startup
2023-05-06 00:23:28 -07:00
James Lu
ccd14af0c8 settings: treat empty environment variables as set (#77)
This allows disabling specific options like dns_interface or whois via environment variables.

ref: https://github.com/spf13/viper#working-with-environment-variables
2023-05-05 21:36:38 -07:00
Lan Tian
594ca80f50 frontend: fix whois lookup & only show bgpmap nexthop info on the first hop 2023-05-05 20:20:12 -07:00
Lan Tian
5625058e71 frontend: use ASN as bgpmap node identifier (instead of resolved whois result) 2023-05-05 19:52:30 -07:00
Lan Tian
7efa3237a9 frontend: refactor bgpmap code to fix #75 2023-05-05 01:58:05 -07:00
Lan Tian
7b0c8c0556 general: bump go version in go.mod 2023-01-26 22:01:47 -08:00
dependabot[bot]
ffd9165062 build(deps): bump github.com/spf13/viper in /frontend (#73)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 10:50:42 -08:00
dependabot[bot]
24fd5203e8 build(deps): bump github.com/spf13/viper from 1.14.0 to 1.15.0 in /proxy (#74)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 10:50:30 -08:00
Lan Tian
49a05767c1 ci: bump version for go-release-action 2023-01-08 01:16:23 -06:00
Lan Tian
e7010f75f8 release: v1.2.0 2023-01-06 23:05:05 -06:00
Yuhui Xu
dba2af7634 proxy: fix description for --traceroute_flags (#70) 2022-12-27 15:38:41 -06:00
Yuhui Xu
049775319b proxy: autodetect traceroute args on startup (#69) 2022-12-25 15:41:29 -06:00
Lan Tian
47c66b125c release: v1.1.1 2022-12-18 16:26:47 -06:00
Yuhui Xu
9e17b116f1 frontend: refactor bgpmap and fix node colors (#67)
* frontend: refactor bgpmap and fix node colors

* frontend: alternative way to test bgpmap
2022-12-07 16:30:19 -06:00
Lan Tian
335ad40634 release: v1.1.0 2022-11-27 17:22:21 -06:00
dependabot[bot]
6ec0f2e7a6 build(deps): bump github.com/spf13/viper from 1.13.0 to 1.14.0 in /proxy (#65)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.13.0...v1.14.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 20:26:44 -06:00
dependabot[bot]
4b73cf0fcb build(deps): bump github.com/spf13/viper in /frontend (#64)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.13.0...v1.14.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 20:26:37 -06:00
Klara Modin
3b1d001543 frontend: sortable tables in summary (#61)
Adapted from https://stackoverflow.com/a/57080195.
Additions:
1. sortTable accepts a secondary column and sorting direction. The 'Name'
   column (number 0) is always used for the secondary
2. use classes 'ascSorted' and 'descSorted' to toggle between ascending and
   descending order
3. in the table functions, use .innerHTML instead of .innnerText so the
   link to detailed protocol information does not get lost. Also
   preserve .classList
2022-09-18 15:58:20 -05:00
dependabot[bot]
675cb26ed1 build(deps): bump github.com/spf13/viper from 1.12.0 to 1.13.0 in /proxy (#63)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 12:22:03 -05:00
dependabot[bot]
556d3e50d3 build(deps): bump github.com/spf13/viper in /frontend (#62)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 12:21:56 -05:00
Lan Tian
06796f546e general: remove failing docker image build tasks for PRs 2022-08-25 11:42:41 -05:00
Potat0
d029d6684c Fix the wrong order of examples (#60) 2022-08-17 11:44:35 -05:00
日下部 詩
5ce0f55f35 1. support local whois. 2 add some useful bird command (#59) 2022-08-11 22:34:39 -04:00
Lan Tian
890ab51b07 release: v1.0.0 2022-08-05 22:36:43 -04:00
Lan Tian
8e4a35cc8c general: fix GOARCH for ARM 32 bit 2022-08-05 22:33:33 -04:00
Lan Tian
97f3c6088f general: add GitHub actions for releasing binaries 2022-08-05 22:29:30 -04:00
Yuhui Xu
982326a678 frontend: fix XSS (#57) (#58) 2022-08-05 21:59:18 -04:00
Tristan Heaven
4b3980f6bd Fix navbar_brand_url config (#56) 2022-07-28 09:54:39 -04:00
Yuhui Xu
6f6b2bd283 general: support reading config files (#55) 2022-07-08 23:13:10 -04:00
Yuhui Xu
892a7bee22 frontend: support listening on unix socket (#54) 2022-07-08 21:14:11 -04:00
Nicolas Lorin
348295b9aa frontend: add the abilities to customized timeout time (#51)
* main.go: add timeout setting

* lgproxy.go: use timeout setting when querying server

* README.md: add new timeout setting
2022-02-08 02:29:05 -06:00
Kioubit
950c018b18 Confirm that bird access was restricted (#49)
Co-authored-by: Kioubit <kioubit@localhost.invalid>
2022-01-18 03:03:09 -06:00
herver
26efeb4996 Add name filter feature (#48)
This uses a RE2 regexp to hide protocols which name matches the expression
2022-01-18 03:01:57 -06:00
Lan Tian
5a5dfbc93f general: add docker hub links to readme 2022-01-09 01:51:36 -06:00
Lan Tian
f60a292129 general: build docker images with correct arch label 2022-01-09 01:45:00 -06:00
James Lu
e7f6026854 Add BIRDLG_TRACEROUTE_RAW option to leave traceroute output in the default format (#47) 2022-01-09 00:14:31 -06:00
Lan Tian
a4e0f4c193 frontend: skip network related tests when unavailable
Fix #46
2022-01-09 00:10:14 -06:00
日下部 詩
af5b653326 BIRDLG_BGPMAP_INFO 選項 (#44)
* BIRDLG_BGPMAP_INFO

update the paramater

description fix for bgpmap_test

singleline and multiline

* Static file instead of jsdelivr; favicon.ico

Co-authored-by: testscript <testscript@example.com>
2021-12-20 03:35:43 -06:00
日下部 詩
58847759b3 一些小改動 (#42)
* 1. remove ":" at the start of port assignement. 2. use BIRDLG_PROXY_PORT at proxy. 3. add custom URL to brand

* goto / if only one server

* add BIRDLG_TRACEROUTE_BIN
2021-11-09 12:27:02 -06:00
Yuhui Xu
6481e7cc8d frontend: fix uninitialized buffer (#41) 2021-09-26 13:26:07 -05:00
James Lu
2166d73b3d frontend: add filtering by protocol type to summary tables (#40)
* frontend: add option to filter by protocol type

Closes #33.

* frontend: use case insensitive comparisons for protocol filter
2021-09-07 15:17:16 -05:00
Yuhui Xu
a64d839e2c frontend: limit fetched response size to 64KB (#39) 2021-09-02 20:21:28 -05:00
James Lu
1a3c618522 frontend: BGPmap improvements (#36)
* bgpmap: Compact nexthop info into an edge label

* bgpmap: parse and show non-BGP routes

* bgpmap: Misc tweaks

- Show the protocol name instead of the ASN in edge labels
- Correctly draw only the primary path if there are multiple routes to the first neighbour ASN in a path
- Use a smaller font size for edge labels

* bgpmap_test: update to match new changes

* bgpmap: Split route info on all (non-empty) rta_dest_names values
2021-08-31 09:44:14 -05:00
Yuhui Xu
fbd190628c general: add go 1.16 requirement to readme [skip ci] (#37) 2021-08-30 23:46:14 -05:00
Yuhui Xu
823b639245 frontend: also filter whois privacy redacted lines (#34) 2021-08-28 22:02:03 -05:00
Yuhui Xu
b0c0e5442d frontend: set lgproxy request timeout to 120s (#31)
lgproxy traceroutecan be really slow if dns resolve doesnt work well.
2021-08-04 00:30:38 +08:00
Yuhui Xu
4e4ce89418 frontend: set timeout longer for lgproxy requests (#30) 2021-08-03 11:46:05 +08:00
Yuhui Xu
234aadadd9 frontend: specify timeout for requests (#29) 2021-08-02 18:46:43 +08:00
Lan Tian
bee26f421c frontend: resolve asn in dns/whois/fail order & fix tests 2021-07-31 17:11:20 +08:00
Yuhui Xu
2e0cb131ca Merge pull request #27 from miegl/master
frontend: optional ASN resolution using whois
2021-07-31 17:02:25 +08:00
Josef Miegl
4c248c638a frontend: optional asn resolution using whois 2021-07-30 16:54:41 +02:00
Yuhui Xu
3550362a4d Merge pull request #26 from sesa-me/master
Refactor to use go:embed
2021-07-14 22:13:36 +08:00
Simon Marsh
256a80646f - Refactor file embedding to use Go 1.16 embed functionality.
- Remove references to previous bindata packages from build scripts and docs
2021-07-13 11:54:35 +01:00
Yuhui Xu
03c42eb1e8 Merge pull request #25 from outloudvi/patch-1
doc: add --net-specific-mode
2021-07-03 22:20:56 +08:00
Outvi V
aea85e774c doc: add --net-specific-mode 2021-07-03 12:33:49 +08:00
Yuhui Xu
80d9351a58 Merge pull request #24 from xddxdd/lantian-dev
frontend: allow long lines if result is short
2021-06-21 01:01:37 +08:00
Lan Tian
5e0bc081e6 frontend: allow long lines if result is short 2021-06-21 00:57:26 +08:00
Yuhui Xu
4d53d1f095 Merge pull request #23 from xddxdd/lantian-dev
frontend: change behavior of whois shorten mode
2021-06-21 00:49:37 +08:00
Lan Tian
5883015294 frontend: change behavior of whois shorten mode 2021-06-21 00:44:44 +08:00
Yuhui Xu
80e66a7a81 Merge pull request #22 from xddxdd/lantian-dev
frontend: add generic whois shorten mode
2021-06-20 02:24:49 +08:00
Lan Tian
41329da7cb frontend: add generic whois shorten mode 2021-06-20 02:20:18 +08:00
Yuhui Xu
8e56705205 Merge pull request #21 from xddxdd/lantian-dev
frontend: fix typo
2021-06-19 16:42:01 +08:00
Lan Tian
6a8b3a0e55 frontend: fix typo 2021-06-19 16:36:18 +08:00
Yuhui Xu
83ab403706 Merge pull request #20 from xddxdd/lantian-dev
frontend: limit telegram commands by bot name
2021-06-19 16:27:17 +08:00
Lan Tian
7c7814cc7b frontend: limit telegram commands by bot name 2021-06-19 16:23:43 +08:00
Yuhui Xu
8598060cc0 Merge pull request #19 from xddxdd/lantian-dev
Add instruction for create Dockerfile
2021-05-21 21:11:00 +08:00
Lan Tian
bda06ddd5e Add instruction for create Dockerfile 2021-05-21 21:09:50 +08:00
Yuhui Xu
f404072ab8 Merge pull request #18 from xddxdd/dependabot/add-v2-config-file
Upgrade to GitHub-native Dependabot
2021-05-01 23:21:14 +08:00
69 changed files with 9567 additions and 816 deletions

View File

@@ -1,61 +0,0 @@
version: 2.1
workflows:
docker:
jobs:
- build
- deploy:
context:
- docker
requires:
- build
matrix:
parameters:
program: [frontend, proxy]
# latest is amd64 arch + push to default latest tag
image_arch: [latest, i386, arm32v7, arm64v8, ppc64le, s390x]
filters:
branches:
only: master
jobs:
build:
docker:
- image: circleci/golang:1.15
working_directory: /go/src/github.com/xddxdd/bird-lg-go
steps:
- checkout
- run: go get -v -t -d ./...
- run: go get -u github.com/kevinburke/go-bindata/...
- run: cd frontend && go generate
- run: go test -v ./...
deploy:
docker:
- image: circleci/golang:1.15
working_directory: /go/src/github.com/xddxdd/bird-lg-go
parameters:
image_arch:
type: string
program:
type: string
steps:
- checkout
- setup_remote_docker:
version: 19.03.13
- run:
name: Install GPP
command: |
sudo apt-get update && sudo apt-get install -y gpp
- run:
name: Build Docker image
environment:
IMAGE_ARCH: << parameters.image_arch >>
PROGRAM: << parameters.program >>
BUILD_ID: << pipeline.number >>
command: |
make -f Makefile.docker _crossbuild
echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
make -f Makefile.docker \
DOCKER_USERNAME=$DOCKER_USERNAME \
BUILD_ID=circleci-build$BUILD_ID \
$PROGRAM/$IMAGE_ARCH

16
.github/workflows/auto-merge.yml vendored Normal file
View 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 }}

127
.github/workflows/develop.yaml vendored Normal file
View File

@@ -0,0 +1,127 @@
on:
push:
branches:
- 'master'
pull_request:
branches:
- 'master'
jobs:
go-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Golang
uses: actions/setup-go@v4
- name: Run frontend unit test
run: |
export GO111MODULE=on
cd frontend
go get -v -t -d ./...
go test -v ./...
cd ..
- name: Run proxy unit test
run: |
export GO111MODULE=on
cd proxy
go get -v -t -d ./...
go test -v ./...
cd ..
docker-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Test whois binary in frontend image
run: |
docker build -t local/frontend frontend/
docker run --rm --net host --entrypoint whois local/frontend -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
- name: Test traceroute binary in proxy image
run: |
docker build -t local/proxy proxy/
docker run --rm --net host --entrypoint traceroute local/proxy 127.0.0.1 || exit 1
docker run --rm --net host --entrypoint traceroute local/proxy ::1 || exit 1
- 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:
- go-test
- docker-test
if: github.event_name != 'pull_request'
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build frontend docker image
uses: docker/build-push-action@v4
with:
context: '{{defaultContext}}:frontend'
platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7
push: true
tags: |
xddxdd/bird-lg-go:develop
xddxdd/bird-lg-go:develop-${{ github.sha }}
ghcr.io/xddxdd/bird-lg-go:frontend-develop
ghcr.io/xddxdd/bird-lg-go:frontend-develop-${{ github.sha }}
- name: Build proxy docker image
uses: docker/build-push-action@v4
with:
context: '{{defaultContext}}:proxy'
platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7
push: true
tags: |
xddxdd/bird-lgproxy-go:develop
xddxdd/bird-lgproxy-go:develop-${{ github.sha }}
ghcr.io/xddxdd/bird-lg-go:proxy-develop
ghcr.io/xddxdd/bird-lg-go:proxy-develop-${{ github.sha }}
- 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

100
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,100 @@
on:
release:
types: [created]
jobs:
go-release:
name: Release Go Binary
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
goos: [linux, windows, darwin]
goarch: ["386", amd64, "arm", arm64]
exclude:
- goarch: "386"
goos: darwin
- goarch: "arm"
goos: darwin
- goarch: "arm"
goos: windows
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Release frontend
uses: wangyoucao577/go-release-action@v1.40
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
project_path: "./frontend"
binary_name: "bird-lg-go"
- name: Release proxy
uses: wangyoucao577/go-release-action@v1.40
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
project_path: "./proxy"
binary_name: "bird-lgproxy-go"
docker-release:
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build frontend docker image
uses: docker/build-push-action@v4
with:
context: '{{defaultContext}}:frontend'
platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7
push: true
tags: |
xddxdd/bird-lg-go:latest
xddxdd/bird-lg-go:${{ github.event.release.tag_name }}
ghcr.io/xddxdd/bird-lg-go:frontend
ghcr.io/xddxdd/bird-lg-go:frontend-${{ github.event.release.tag_name }}
- name: Build proxy docker image
uses: docker/build-push-action@v4
with:
context: '{{defaultContext}}:proxy'
platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7
push: true
tags: |
xddxdd/bird-lgproxy-go:latest
xddxdd/bird-lgproxy-go:${{ github.event.release.tag_name }}
ghcr.io/xddxdd/bird-lg-go:proxy
ghcr.io/xddxdd/bird-lg-go:proxy-${{ github.event.release.tag_name }}
- 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
View File

@@ -20,7 +20,3 @@ proxy/proxy
# don't include generated bindata file
frontend/bindata.go
# don't include generated Dockerfiles
frontend/Dockerfile.*
proxy/Dockerfile.*

View File

@@ -9,5 +9,5 @@ proxy:
all: frontend proxy
install:
install -m 755 frontend/frontend /usr/local/bin/frontend
install -m 755 proxy/proxy /usr/local/bin/proxy
install -m 755 frontend/frontend /usr/local/bin/bird-lg-go
install -m 755 proxy/proxy /usr/local/bin/bird-lgproxy-go

View File

@@ -1,77 +0,0 @@
# Basic definitions
DOCKER_USERNAME := xddxdd
ARCHITECTURES := amd64 i386 arm32v7 arm64v8 ppc64le s390x
IMAGES := frontend proxy
# General Purpose Preprocessor config
GPP_INCLUDE_DIR := include
GPP_FLAGS_U := "" "" "(" "," ")" "(" ")" "\#" ""
GPP_FLAGS_M := "\#" "\n" " " " " "\n" "(" ")"
GPP_FLAGS_EXTRA := +c "\\\n" ""
GPP_FLAGS := -I ${GPP_INCLUDE_DIR} --nostdinc -U ${GPP_FLAGS_U} -M ${GPP_FLAGS_M} ${GPP_FLAGS_EXTRA}
BUILD_ID ?= $(shell date +%Y%m%d%H%M)
define create-image-arch-target
frontend/Dockerfile.$1: frontend/template.Dockerfile
@gpp ${GPP_FLAGS} -D ARCH_$(shell echo $1 | tr a-z A-Z) -o frontend/Dockerfile.$1 frontend/template.Dockerfile || rm -rf frontend/Dockerfile.$1
frontend/$1: frontend/Dockerfile.$1
@if [ -f frontend/Dockerfile.$1 ]; then \
docker build --pull --no-cache -t ${DOCKER_USERNAME}/bird-lg-go:$1-${BUILD_ID} -f frontend/Dockerfile.$1 frontend || exit 1; \
docker push ${DOCKER_USERNAME}/bird-lg-go:$1-${BUILD_ID} || exit 1; \
docker tag ${DOCKER_USERNAME}/bird-lg-go:$1-${BUILD_ID} ${DOCKER_USERNAME}/bird-lg-go:$1 || exit 1; \
docker push ${DOCKER_USERNAME}/bird-lg-go:$1 || exit 1; \
else \
echo "Dockerfile generation failed, see error above"; \
exit 1; \
fi
proxy/Dockerfile.$1: proxy/template.Dockerfile
@gpp ${GPP_FLAGS} -D ARCH_$(shell echo $1 | tr a-z A-Z) -o proxy/Dockerfile.$1 proxy/template.Dockerfile || rm -rf proxy/Dockerfile.$1
proxy/$1: proxy/Dockerfile.$1
@if [ -f proxy/Dockerfile.$1 ]; then \
docker build --pull --no-cache -t ${DOCKER_USERNAME}/bird-lgproxy-go:$1-${BUILD_ID} -f proxy/Dockerfile.$1 proxy || exit 1; \
docker push ${DOCKER_USERNAME}/bird-lgproxy-go:$1-${BUILD_ID} || exit 1; \
docker tag ${DOCKER_USERNAME}/bird-lgproxy-go:$1-${BUILD_ID} ${DOCKER_USERNAME}/bird-lgproxy-go:$1 || exit 1; \
docker push ${DOCKER_USERNAME}/bird-lgproxy-go:$1 || exit 1; \
else \
echo "Dockerfile generation failed, see error above"; \
exit 1; \
fi
endef
$(foreach arch,${ARCHITECTURES},$(eval $(call create-image-arch-target,$(arch))))
frontend:$(foreach arch,latest ${ARCHITECTURES},frontend/${arch})
frontend/latest: frontend/amd64
@docker tag ${DOCKER_USERNAME}/bird-lg-go:amd64-${BUILD_ID} ${DOCKER_USERNAME}/bird-lg-go:${BUILD_ID} || exit 1
@docker push ${DOCKER_USERNAME}/bird-lg-go:${BUILD_ID} || exit 1
@docker tag ${DOCKER_USERNAME}/bird-lg-go:amd64-${BUILD_ID} ${DOCKER_USERNAME}/bird-lg-go:latest || exit 1
@docker push ${DOCKER_USERNAME}/bird-lg-go:latest || exit 1
proxy:$(foreach arch,latest ${ARCHITECTURES},proxy/${arch})
proxy/latest: proxy/amd64
@docker tag ${DOCKER_USERNAME}/bird-lgproxy-go:amd64-${BUILD_ID} ${DOCKER_USERNAME}/bird-lgproxy-go:${BUILD_ID} || exit 1
@docker push ${DOCKER_USERNAME}/bird-lgproxy-go:${BUILD_ID} || exit 1
@docker tag ${DOCKER_USERNAME}/bird-lgproxy-go:amd64-${BUILD_ID} ${DOCKER_USERNAME}/bird-lgproxy-go:latest || exit 1
@docker push ${DOCKER_USERNAME}/bird-lgproxy-go:latest || exit 1
.DEFAULT_GOAL := images
.DELETE_ON_ERROR:
.SECONDARY:
# Target to enable multiarch support
_crossbuild:
@docker run --rm --privileged multiarch/qemu-user-static --reset -p yes >/dev/null
dockerfiles: $(foreach image,${IMAGES},$(foreach arch,${ARCHITECTURES},$(image)/Dockerfile.$(arch)))
images: $(foreach image,${IMAGES},$(image))
clean:
@rm -rf */Dockerfile.{$(shell echo ${ARCHITECTURES} | sed "s/ /,/g")}

218
README.md

File diff suppressed because it is too large Load Diff

1
RELEASE Normal file
View File

@@ -0,0 +1 @@
v1.3.9

View File

@@ -153,9 +153,11 @@ Request:
```json
{
"servers": [],
"type": "server_list",
"args": ""
"servers": [
"alpha"
],
"type": "bird",
"args": "show status"
}
```
@@ -179,11 +181,9 @@ Request:
```json
{
"servers": [
"alpha"
],
"type": "bird",
"args": "show status"
"servers": [],
"type": "server_list",
"args": ""
}
```

22
docs/Telegram.md Normal file
View File

@@ -0,0 +1,22 @@
# Telegram Bot Webhook
The frontend can act as a Telegram Bot webhook endpoint, to add BGP route/traceroute/whois lookup functionality to your tech group.
There is no configuration necessary on the frontend, just start it up normally.
Set your Telegram Bot webhook URL to `https://your.frontend.com/telegram/alpha+beta+gamma`, where `alpha+beta+gamma` is the list of servers to be queried on Telegram commands, separated by `+`.
You may omit `alpha+beta+gamma` to use all your servers, but it is not recommended when you have lots of servers, or the message would be too long and hard to read.
## Example of setting the webhook
```bash
curl "https://api.telegram.org/bot${BOT_TOKEN}/setWebhook?url=https://your.frontend.com:5000/telegram/alpha+beta+gamma"
```
## Supported commands
- `path`: Show bird's ASN path to target IP
- `route`: Show bird's preferred route to target IP
- `trace`: Traceroute to target IP/domain
- `whois`: Whois query

33
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,33 @@
FROM golang AS step_0
ENV CGO_ENABLED=0 GO111MODULE=on
WORKDIR /root
COPY . .
RUN go build -ldflags "-w -s" -o /frontend
################################################################################
FROM alpine:edge AS step_1
WORKDIR /root
RUN apk add --no-cache build-base pkgconf perl gettext \
libidn2-dev libidn2-static libunistring-dev libunistring-static gnu-libiconv-dev
RUN wget https://github.com/rfc1036/whois/archive/refs/tags/v5.5.18.tar.gz \
-O whois-5.5.18.tar.gz
RUN tar xvf whois-5.5.18.tar.gz \
&& cd whois-5.5.18 \
&& sed -i "s/#if defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 200112L/#if 1/g" config.h \
&& make whois -j4 \
LDFLAGS="-static" CONFIG_FILE="/etc/whois.conf" PKG_CONFIG="pkg-config --static" HAVE_ICONV=1 \
&& strip /root/whois-5.5.18/whois
################################################################################
FROM scratch AS step_2
ENV PATH=/
ENV BIRDLG_WHOIS=/whois
COPY --from=step_0 /frontend /
COPY --from=step_1 /root/whois-5.5.18/whois /
COPY --from=step_1 /etc/services /etc/services
ENTRYPOINT ["/frontend"]

View File

@@ -1,5 +1,3 @@
.PHONY: all
all:
go get -u github.com/kevinburke/go-bindata/...
go generate
go build -ldflags "-w -s" -o frontend

View File

@@ -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{
@@ -113,7 +117,7 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
} else {
handler := apiHandlerMap[request.Type]
if handler == nil {
response = apiErrorHandler(errors.New("Invalid request type"))
response = apiErrorHandler(errors.New("invalid request type"))
} else {
response = handler(request)
}

210
frontend/api_test.go Normal file
View File

@@ -0,0 +1,210 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/jarcoal/httpmock"
"github.com/magiconair/properties/assert"
)
func TestApiServerListHandler(t *testing.T) {
setting.servers = []string{"alpha", "beta", "gamma"}
response := apiServerListHandler(apiRequest{})
assert.Equal(t, len(response.Result), 3)
assert.Equal(t, response.Result[0].(apiGenericResultPair).Server, "alpha")
assert.Equal(t, response.Result[1].(apiGenericResultPair).Server, "beta")
assert.Equal(t, response.Result[2].(apiGenericResultPair).Server, "gamma")
}
func TestApiGenericHandlerFactory(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpResponse := httpmock.NewStringResponder(200, BirdSummaryData)
httpmock.RegisterResponder("GET", "http://alpha:8000/bird?q="+url.QueryEscape("show protocols"), httpResponse)
setting.servers = []string{"alpha"}
setting.domain = ""
setting.proxyPort = 8000
request := apiRequest{
Servers: setting.servers,
Type: "bird",
Args: "show protocols",
}
handler := apiGenericHandlerFactory("bird")
response := handler(request)
assert.Equal(t, response.Error, "")
result := response.Result[0].(*apiGenericResultPair)
assert.Equal(t, result.Server, "alpha")
assert.Equal(t, result.Data, BirdSummaryData)
}
func TestApiSummaryHandler(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpResponse := httpmock.NewStringResponder(200, BirdSummaryData)
httpmock.RegisterResponder("GET", "http://alpha:8000/bird?q="+url.QueryEscape("show protocols"), httpResponse)
setting.servers = []string{"alpha"}
setting.domain = ""
setting.proxyPort = 8000
request := apiRequest{
Servers: setting.servers,
Type: "summary",
Args: "",
}
response := apiSummaryHandler(request)
assert.Equal(t, response.Error, "")
summary := response.Result[0].(*apiSummaryResultPair)
assert.Equal(t, summary.Server, "alpha")
// Protocol list will be sorted
assert.Equal(t, summary.Data[1].Name, "device1")
assert.Equal(t, summary.Data[1].Proto, "Device")
assert.Equal(t, summary.Data[1].Table, "---")
assert.Equal(t, summary.Data[1].State, "up")
assert.Equal(t, summary.Data[1].Since, "2021-08-27")
assert.Equal(t, summary.Data[1].Info, "")
}
func TestApiSummaryHandlerError(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
httpResponse := httpmock.NewStringResponder(200, "Mock backend error")
httpmock.RegisterResponder("GET", "http://alpha:8000/bird?q="+url.QueryEscape("show protocols"), httpResponse)
setting.servers = []string{"alpha"}
setting.domain = ""
setting.proxyPort = 8000
request := apiRequest{
Servers: setting.servers,
Type: "summary",
Args: "",
}
response := apiSummaryHandler(request)
assert.Equal(t, response.Error, "")
summary := response.Result[0].(*apiSummaryResultPair)
assert.Equal(t, summary.Error, "Mock backend error")
}
func TestApiWhoisHandler(t *testing.T) {
expectedData := "Mock Data"
server := WhoisServer{
t: t,
expectedQuery: "AS6939",
response: expectedData,
}
server.Listen()
go server.Run()
defer server.Close()
setting.whoisServer = server.server.Addr().String()
request := apiRequest{
Servers: []string{},
Type: "",
Args: "AS6939",
}
response := apiWhoisHandler(request)
assert.Equal(t, response.Error, "")
whoisResult := response.Result[0].(apiGenericResultPair)
assert.Equal(t, whoisResult.Server, "")
assert.Equal(t, whoisResult.Data, expectedData)
}
func TestApiErrorHandler(t *testing.T) {
err := errors.New("Mock Error")
response := apiErrorHandler(err)
assert.Equal(t, response.Error, "Mock Error")
}
func TestApiHandler(t *testing.T) {
setting.servers = []string{"alpha", "beta", "gamma"}
request := apiRequest{
Servers: []string{},
Type: "server_list",
Args: "",
}
requestJson, err := json.Marshal(request)
if err != nil {
t.Error(err)
}
r := httptest.NewRequest(http.MethodGet, "/api", bytes.NewReader(requestJson))
w := httptest.NewRecorder()
apiHandler(w, r)
var response apiResponse
err = json.Unmarshal(w.Body.Bytes(), &response)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(response.Result), 3)
// Hard to unmarshal JSON into apiGenericResultPair objects, won't check here
}
func TestApiHandlerBadJSON(t *testing.T) {
setting.servers = []string{"alpha", "beta", "gamma"}
r := httptest.NewRequest(http.MethodGet, "/api", strings.NewReader("{bad json}"))
w := httptest.NewRecorder()
apiHandler(w, r)
var response apiResponse
err := json.Unmarshal(w.Body.Bytes(), &response)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(response.Result), 0)
}
func TestApiHandlerInvalidType(t *testing.T) {
setting.servers = []string{"alpha", "beta", "gamma"}
request := apiRequest{
Servers: setting.servers,
Type: "invalid_type",
Args: "",
}
requestJson, err := json.Marshal(request)
if err != nil {
t.Error(err)
}
r := httptest.NewRequest(http.MethodGet, "/api", bytes.NewReader(requestJson))
w := httptest.NewRecorder()
apiHandler(w, r)
var response apiResponse
err = json.Unmarshal(w.Body.Bytes(), &response)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(response.Result), 0)
}

83
frontend/asn_cache.go Normal file
View File

@@ -0,0 +1,83 @@
package main
import (
"fmt"
"net"
"strings"
)
type ASNCache map[string]string
func (cache ASNCache) _lookup(asn string) string {
// Try to get ASN representation using DNS
if setting.dnsInterface != "" {
records, err := net.LookupTXT(fmt.Sprintf("AS%s.%s", asn, setting.dnsInterface))
if err == nil {
result := strings.Join(records, " ")
if resultSplit := strings.Split(result, " | "); len(resultSplit) > 1 {
result = strings.Join(resultSplit[1:], "\n")
}
return fmt.Sprintf("AS%s\n%s", asn, result)
}
}
// Try to get ASN representation using WHOIS
if setting.whoisServer != "" {
if setting.bgpmapInfo == "" {
setting.bgpmapInfo = "asn,as-name,ASName,descr"
}
records := whois(fmt.Sprintf("AS%s", asn))
if records != "" {
recordsSplit := strings.Split(records, "\n")
var result []string
for _, title := range strings.Split(setting.bgpmapInfo, ",") {
if title == "asn" {
result = append(result, "AS"+asn)
}
}
for _, title := range strings.Split(setting.bgpmapInfo, ",") {
allow_multiline := false
if title[0] == ':' && len(title) >= 2 {
title = title[1:]
allow_multiline = true
}
for _, line := range recordsSplit {
if len(line) == 0 || line[0] == '%' || !strings.Contains(line, ":") {
continue
}
linearr := strings.SplitN(line, ":", 2)
line_title := linearr[0]
content := strings.TrimSpace(linearr[1])
if line_title != title {
continue
}
result = append(result, content)
if !allow_multiline {
break
}
}
}
if len(result) > 0 {
return strings.Join(result, "\n")
}
}
}
return ""
}
func (cache ASNCache) Lookup(asn string) string {
cachedValue, cacheOk := cache[asn]
if cacheOk {
return cachedValue
}
result := cache._lookup(asn)
if len(result) == 0 {
result = fmt.Sprintf("AS%s", asn)
}
cache[asn] = result
return result
}

View File

@@ -0,0 +1,52 @@
package main
import (
"strings"
"testing"
"github.com/magiconair/properties/assert"
)
func TestGetASNRepresentationDNS(t *testing.T) {
checkNetwork(t)
setting.dnsInterface = "asn.cymru.com"
setting.whoisServer = ""
cache := make(ASNCache)
result := cache.Lookup("6939")
if !strings.Contains(result, "HURRICANE") {
t.Errorf("Lookup AS6939 failed, got %s", result)
}
}
func TestGetASNRepresentationDNSFallback(t *testing.T) {
checkNetwork(t)
setting.dnsInterface = "invalid.example.com"
setting.whoisServer = "whois.arin.net"
cache := make(ASNCache)
result := cache.Lookup("6939")
if !strings.Contains(result, "HURRICANE") {
t.Errorf("Lookup AS6939 failed, got %s", result)
}
}
func TestGetASNRepresentationWhois(t *testing.T) {
checkNetwork(t)
setting.dnsInterface = ""
setting.whoisServer = "whois.arin.net"
cache := make(ASNCache)
result := cache.Lookup("6939")
if !strings.Contains(result, "HURRICANE") {
t.Errorf("Lookup AS6939 failed, got %s", result)
}
}
func TestGetASNRepresentationFallback(t *testing.T) {
setting.dnsInterface = ""
setting.whoisServer = ""
cache := make(ASNCache)
result := cache.Lookup("6939")
assert.Equal(t, result, "AS6939")
}

BIN
frontend/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,73 @@
// adapted from https://stackoverflow.com/a/57080195
document.querySelectorAll('table.sortable')
.forEach((table)=> {
table.querySelectorAll('th')
.forEach((element, columnNo) => {
element.addEventListener('click', event => {
if(element.classList.contains('ascSorted')) {
dir = -1;
element.classList.remove('ascSorted');
element.classList.add('descSorted');
element.innerText = element.innerText.slice(0,-2) + " ↓";
} else if(element.classList.contains('descSorted')) {
dir = 1;
element.classList.remove('descSorted');
element.classList.add('ascSorted');
element.innerText = element.innerText.slice(0,-2) + " ↑";
} else {
dir = 1;
element.classList.add('ascSorted');
element.innerText += " ↑";
}
sortTable(table, columnNo, 0, dir, 1);
});
});
});
function sortTable(table, priCol, secCol, priDir, secDir) {
const tableBody = table.querySelector('tbody');
const tableData = table2data(tableBody);
tableData.sort((a, b) => {
if(a[priCol] === b[priCol]) {
if(a[secCol] > b[secCol]) {
return secDir;
} else {
return -secDir;
}
} else if(a[priCol] > b[priCol]) {
return priDir;
} else {
return -priDir;
}
});
data2table(tableBody, tableData);
}
function table2data(tableBody) {
const tableData = [];
tableBody.querySelectorAll('tr')
.forEach(row => {
const rowData = [];
row.querySelectorAll('td')
.forEach(cell => {
rowData.push(cell.innerHTML);
});
rowData.classList = row.classList.toString();
tableData.push(rowData);
});
return tableData;
}
function data2table(tableBody, tableData) {
tableBody.querySelectorAll('tr')
.forEach((row, i) => {
const rowData = tableData[i];
row.classList = rowData.classList;
row.querySelectorAll('td')
.forEach((cell, j) => {
cell.innerHTML = rowData[j];
});
tableData.push(rowData);
});
}

View File

@@ -0,0 +1,27 @@
<h2>BGPmap: {{ html .Target }}</h2>
<div id="bgpmap">
</div>
<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(decodeBase64({{ .Result }}))
.then(element => {
document.getElementById("bgpmap").appendChild(element);
})
.catch(error => {
document.getElementById("bgpmap").innerHTML = "<pre>"+error+"</pre>"
});
</script>

View File

@@ -1,18 +1,32 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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="https://cdn.jsdelivr.net/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>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">{{ .Brand }}</a>
<a class="navbar-brand" href="{{ .BrandURL }}">{{ .Brand }}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
@@ -28,13 +42,24 @@
{{ end }}
<ul class="navbar-nav mr-auto">
<li class="nav-item">
{{ if eq .AllServersURLCustom "all" }}
<a class="nav-link{{ if .AllServersLinkActive }} active{{ end }}"
href="/{{ $option }}/{{ .AllServersURL }}/{{ $target }}"> All Servers </a>
href="/{{ $option }}/{{ .AllServersURL }}/{{ $target }}"> {{ .AllServerTitle }} </a>
{{ else }}
<a class="nav-link active"
href="{{ .AllServersURLCustom }}"> {{ .AllServerTitle }} </a>
{{ end }}
</li>
{{ range $k, $v := .ServersEscaped }}
{{ $length := len .Servers }}
{{ range $k, $v := .Servers }}
<li class="nav-item">
{{ if gt $length 1 }}
<a class="nav-link{{ if eq $server $v }} active{{ end }}"
href="/{{ $option }}/{{ $v }}/{{ $target }}">{{ html (index $.ServersDisplay $k) }}</a>
{{ else }}
<a class="nav-link{{ if eq $server $v }} active{{ end }}"
href="/">{{ html (index $.ServersDisplay $k) }}</a>
{{ end }}
</li>
{{ end }}
</ul>
@@ -48,7 +73,7 @@
<option value="{{ html $k }}"{{ if eq $k $.URLOption }} selected{{end}}>{{ html $v }}</option>
{{ end }}
</select>
<input name="server" class="d-none" value="{{ html $server }}">
<input name="server" class="d-none" value="{{ html ($server | pathescape) }}">
<input name="target" class="form-control" placeholder="Target" aria-label="Target" value="{{ html $target }}">
<div class="input-group-append">
<button class="btn btn-outline-success" type="submit">&raquo;</button>
@@ -62,8 +87,9 @@
{{ .Content }}
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/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>
function goto() {

View File

@@ -1,6 +1,6 @@
{{ $ServerName := urlquery .ServerName }}
<table class="table table-striped table-bordered table-sm">
<table class="table table-striped table-bordered table-sm sortable">
<thead>
{{ range .Header }}
<th scope="col">{{ html . }}</th>

View File

@@ -1,122 +1,121 @@
package main
import (
"fmt"
"html"
"net"
"regexp"
"strings"
)
func getASNRepresentation(asn string) string {
records, err := net.LookupTXT(fmt.Sprintf("AS%s.%s", asn, setting.dnsInterface))
if err != nil {
// DNS query failed, only use ASN as output
return fmt.Sprintf("AS%s", asn)
}
// The protocol name for each route (e.g. "ibgp_sea02") is encoded in the form:
//
// unicast [ibgp_sea02 2021-08-27 from fd86:bad:11b7:1::1] * (100/1015) [i]
var protocolNameRe = regexp.MustCompile(`\[(.*?) .*\]`)
result := strings.Join(records, " ")
if resultSplit := strings.Split(result, " | "); len(resultSplit) > 1 {
result = strings.Join(resultSplit[1:], "\\n")
// Try to split the output into one chunk for each route.
// Possible values are defined at https://gitlab.nic.cz/labs/bird/-/blob/v2.0.8/nest/rt-attr.c#L81-87
var routeSplitRe = regexp.MustCompile("(unicast|blackhole|unreachable|prohibited)")
var routeViaRe = regexp.MustCompile(`(?m)^\t(via .*?)$`)
var routeASPathRe = regexp.MustCompile(`(?m)^\tBGP\.as_path: (.*?)$`)
func makeEdgeAttrs(preferred bool) RouteAttrs {
result := RouteAttrs{
"fontsize": "12.0",
}
return fmt.Sprintf("AS%s\\n%s", asn, result)
if preferred {
result["color"] = "red"
}
return result
}
func birdRouteToGraphviz(servers []string, responses []string, target string) string {
graph := make(map[string]string)
// Helper to add an edge
addEdge := func(src string, dest string, attr string) {
key := "\"" + html.EscapeString(src) + "\" -> \"" + html.EscapeString(dest) + "\""
_, present := graph[key]
// Do not remove edge's attributes if it's already present
if present && len(attr) == 0 {
return
}
graph[key] = attr
}
// Helper to set attribute for a point in graph
addPoint := func(name string, attr string) {
key := "\"" + html.EscapeString(name) + "\""
_, present := graph[key]
// Do not remove point's attributes if it's already present
if present && len(attr) == 0 {
return
}
graph[key] = attr
func makePointAttrs(preferred bool) RouteAttrs {
result := RouteAttrs{}
if preferred {
result["color"] = "red"
}
return result
}
func birdRouteToGraph(servers []string, responses []string, target string) RouteGraph {
graph := makeRouteGraph()
graph.AddPoint(target, false, RouteAttrs{"color": "red", "shape": "diamond"})
addPoint("Target: "+target, "[color=red,shape=diamond]")
for serverID, server := range servers {
response := responses[serverID]
if len(response) == 0 {
continue
}
addPoint(server, "[color=blue,shape=box]")
// This is the best split point I can find for bird2
routes := strings.Split(response, "\tvia ")
routeFound := false
for routeIndex, route := range routes {
var routeNexthop string
var routeASPath string
var routePreferred bool = routeIndex > 0 && strings.Contains(routes[routeIndex-1], "*")
// Have to look at previous slice to determine if route is preferred, due to bad split point selection
graph.AddPoint(server, false, RouteAttrs{"color": "blue", "shape": "box"})
routes := routeSplitRe.Split(response, -1)
for _, routeParameter := range strings.Split(route, "\n") {
if strings.HasPrefix(routeParameter, "\tBGP.next_hop: ") {
routeNexthop = strings.TrimPrefix(routeParameter, "\tBGP.next_hop: ")
} else if strings.HasPrefix(routeParameter, "\tBGP.as_path: ") {
routeASPath = strings.TrimPrefix(routeParameter, "\tBGP.as_path: ")
}
}
if len(routeASPath) == 0 {
// Either this is not a BGP route, or the information is incomplete
for routeIndex, route := range routes {
if routeIndex == 0 {
continue
}
// Connect each node on AS path
paths := strings.Split(strings.TrimSpace(routeASPath), " ")
var via string
var paths []string
var routePreferred bool = strings.Contains(route, "*")
// Track non-BGP routes in the output by their protocol name, but draw them altogether in one line
// so that there are no conflicts in the edge label
var protocolName string
for pathIndex := range paths {
paths[pathIndex] = strings.TrimPrefix(paths[pathIndex], "(")
paths[pathIndex] = strings.TrimSuffix(paths[pathIndex], ")")
if match := routeViaRe.FindStringSubmatch(route); len(match) >= 2 {
via = strings.TrimSpace(match[1])
}
// First step starting from originating server
if len(paths) > 0 {
if len(routeNexthop) > 0 {
// Edge from originating server to nexthop
addEdge(server, "Nexthop:\\n"+routeNexthop, (map[bool]string{true: "[color=red]"})[routePreferred])
// and from nexthop to AS
addEdge("Nexthop:\\n"+routeNexthop, getASNRepresentation(paths[0]), (map[bool]string{true: "[color=red]"})[routePreferred])
addPoint("Nexthop:\\n"+routeNexthop, "[shape=diamond]")
routeFound = true
if match := routeASPathRe.FindStringSubmatch(route); len(match) >= 2 {
pathString := strings.TrimSpace(match[1])
if len(pathString) > 0 {
paths = strings.Split(strings.TrimSpace(match[1]), " ")
for i := range paths {
paths[i] = strings.TrimPrefix(paths[i], "(")
paths[i] = strings.TrimSuffix(paths[i], ")")
}
}
}
if match := protocolNameRe.FindStringSubmatch(route); len(match) >= 2 {
protocolName = strings.TrimSpace(match[1])
if routePreferred {
protocolName = protocolName + "*"
}
}
if len(paths) == 0 {
graph.AddEdge(server, target, strings.TrimSpace(protocolName+"\n"+via), makeEdgeAttrs(routePreferred))
continue
}
// Edges between AS
for i := range paths {
var src string
var label string
// Only show nexthop information on the first hop
if i == 0 {
src = server
label = strings.TrimSpace(protocolName + "\n" + via)
} else {
// Edge from originating server to AS
addEdge(server, getASNRepresentation(paths[0]), (map[bool]string{true: "[color=red]"})[routePreferred])
routeFound = true
src = paths[i-1]
label = ""
}
dst := paths[i]
graph.AddEdge(src, dst, label, makeEdgeAttrs(routePreferred))
// Only set color for next step, origin color is set to blue above
graph.AddPoint(dst, true, makePointAttrs(routePreferred))
}
// Following steps, edges between AS
for pathIndex := range paths {
if pathIndex == 0 {
continue
}
addEdge(getASNRepresentation(paths[pathIndex-1]), getASNRepresentation(paths[pathIndex]), (map[bool]string{true: "[color=red]"})[routePreferred])
}
// Last AS to destination
addEdge(getASNRepresentation(paths[len(paths)-1]), "Target: "+target, (map[bool]string{true: "[color=red]"})[routePreferred])
}
if !routeFound {
// Cannot find a path starting from this server
addEdge(server, "Target: "+target, "[color=gray,label=\"?\"]")
src := paths[len(paths)-1]
graph.AddEdge(src, target, "", makeEdgeAttrs(routePreferred))
}
}
// Combine all graphviz commands
var result string
for edge, attr := range graph {
result += edge + " " + attr + ";\n"
}
return "digraph {\n" + result + "}\n"
return graph
}
func birdRouteToGraphviz(servers []string, responses []string, targetName string) string {
graph := birdRouteToGraph(servers, responses, targetName)
return graph.ToGraphviz()
}

178
frontend/bgpmap_graph.go Normal file
View File

@@ -0,0 +1,178 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
type RouteAttrs map[string]string
type RoutePoint struct {
performLookup bool
attrs RouteAttrs
}
type RouteEdgeKey struct {
src string
dest string
}
type RouteEdgeValue struct {
label []string
attrs RouteAttrs
}
type RouteGraph struct {
points map[string]RoutePoint
edges map[RouteEdgeKey]RouteEdgeValue
}
func makeRouteGraph() RouteGraph {
return RouteGraph{
points: make(map[string]RoutePoint),
edges: make(map[RouteEdgeKey]RouteEdgeValue),
}
}
func makeRoutePoint() RoutePoint {
return RoutePoint{
performLookup: false,
attrs: make(RouteAttrs),
}
}
func makeRouteEdgeValue() RouteEdgeValue {
return RouteEdgeValue{
label: []string{},
attrs: make(RouteAttrs),
}
}
func (graph *RouteGraph) attrsToString(attrs RouteAttrs) string {
if len(attrs) == 0 {
return ""
}
result := ""
isFirst := true
for k, v := range attrs {
if isFirst {
isFirst = false
} else {
result += ","
}
result += graph.escape(k) + "=" + graph.escape(v) + ""
}
return "[" + result + "]"
}
func (graph *RouteGraph) escape(s string) string {
buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
err := encoder.Encode(s)
if err != nil {
return err.Error()
} else {
return string(buffer.Bytes())
}
}
func (graph *RouteGraph) AddEdge(src string, dest string, label string, attrs RouteAttrs) {
// Add edges with same src/dest separately, multiple edges with same src/dest could exist
edge := RouteEdgeKey{
src: src,
dest: dest,
}
newValue, exists := graph.edges[edge]
if !exists {
newValue = makeRouteEdgeValue()
}
if len(label) != 0 {
newValue.label = append(newValue.label, label)
}
for k, v := range attrs {
newValue.attrs[k] = v
}
graph.edges[edge] = newValue
}
func (graph *RouteGraph) AddPoint(name string, performLookup bool, attrs RouteAttrs) {
newValue, exists := graph.points[name]
if !exists {
newValue = makeRoutePoint()
}
newValue.performLookup = performLookup
for k, v := range attrs {
newValue.attrs[k] = v
}
graph.points[name] = newValue
}
func (graph *RouteGraph) GetEdge(src string, dest string) *RouteEdgeValue {
key := RouteEdgeKey{
src: src,
dest: dest,
}
value, ok := graph.edges[key]
if ok {
return &value
} else {
return nil
}
}
func (graph *RouteGraph) GetPoint(name string) *RoutePoint {
value, ok := graph.points[name]
if ok {
return &value
} else {
return nil
}
}
func (graph *RouteGraph) ToGraphviz() string {
var result string
asnCache := make(ASNCache)
for name, value := range graph.points {
var representation string
if value.performLookup {
representation = asnCache.Lookup(name)
} else {
representation = name
}
attrsCopy := value.attrs
if attrsCopy == nil {
attrsCopy = make(RouteAttrs)
}
attrsCopy["label"] = representation
result += fmt.Sprintf("%s %s;\n", graph.escape(name), graph.attrsToString(value.attrs))
}
for key, value := range graph.edges {
attrsCopy := value.attrs
if attrsCopy == nil {
attrsCopy = make(RouteAttrs)
}
if len(value.label) > 0 {
attrsCopy["label"] = strings.Join(value.label, "\n")
}
result += fmt.Sprintf("%s -> %s %s;\n", graph.escape(key.src), graph.escape(key.dest), graph.attrsToString(attrsCopy))
}
return "digraph {\n" + result + "}\n"
}

Some files were not shown because too many files have changed in this diff Show More