1
mirror of https://github.com/xddxdd/bird-lg-go synced 2025-10-30 09:40:51 +01:00

23 Commits

Author SHA1 Message Date
Lan Tian
4a8c752157 release: v1.3.11 2025-09-27 01:54:01 -07:00
Lan Tian
5ad6a4d35c frontend: fix race condition when setting up web server 2025-09-27 01:50:53 -07:00
Ljcbaby
5422c8fd8c refactor: deplcate Handle register 2025-09-27 01:50:53 -07:00
Ljcbaby
5042980d79 frontend multi listen 2025-09-27 01:50:53 -07:00
Ljcbaby
7884531a24 proxy multi listen 2025-09-27 01:50:53 -07:00
dependabot[bot]
cc804e81b6 Merge pull request #129 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/viper-1.21.0 2025-09-09 00:07:01 +00:00
dependabot[bot]
c9bab2ae2b Merge pull request #130 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/viper-1.21.0 2025-09-09 00:05:57 +00:00
dependabot[bot]
b9a4f95978 build(deps): bump github.com/spf13/viper from 1.19.0 to 1.21.0 in /proxy
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.19.0 to 1.21.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.19.0...v1.21.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 00:04:35 +00:00
dependabot[bot]
7cd69746df build(deps): bump github.com/spf13/viper in /frontend
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.19.0 to 1.21.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.19.0...v1.21.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 00:04:30 +00:00
dependabot[bot]
e719859d68 Merge pull request #128 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/pflag-1.0.10 2025-09-03 22:06:35 +00:00
dependabot[bot]
5d06affefc build(deps): bump github.com/spf13/pflag from 1.0.8 to 1.0.10 in /proxy
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.8 to 1.0.10.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.8...v1.0.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-03 22:05:01 +00:00
dependabot[bot]
060fe9bf8e Merge pull request #127 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/pflag-1.0.10 2025-09-03 19:13:13 +00:00
dependabot[bot]
f23d36f357 build(deps): bump github.com/spf13/pflag in /frontend
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.8 to 1.0.10.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.8...v1.0.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-03 19:11:24 +00:00
dependabot[bot]
1dbc0fccd2 Merge pull request #126 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/pflag-1.0.8 2025-09-01 00:08:36 +00:00
dependabot[bot]
b2d64d19e3 build(deps): bump github.com/spf13/pflag in /frontend
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.7 to 1.0.8.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.7...v1.0.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-01 00:06:28 +00:00
dependabot[bot]
4dee4b0806 Merge pull request #125 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/pflag-1.0.8 2025-09-01 00:06:18 +00:00
dependabot[bot]
cb279e0459 build(deps): bump github.com/spf13/pflag from 1.0.7 to 1.0.8 in /proxy
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.7 to 1.0.8.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.7...v1.0.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-01 00:04:16 +00:00
dependabot[bot]
31ba36beaf Merge pull request #123 from xddxdd/dependabot/go_modules/frontend/github.com/jarcoal/httpmock-1.4.1 2025-08-20 05:14:21 +00:00
dependabot[bot]
5ab3b95d64 build(deps): bump github.com/jarcoal/httpmock in /frontend
Bumps [github.com/jarcoal/httpmock](https://github.com/jarcoal/httpmock) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/jarcoal/httpmock/releases)
- [Commits](https://github.com/jarcoal/httpmock/compare/v1.4.0...v1.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 05:12:43 +00:00
dependabot[bot]
7bf654f35f Merge pull request #122 from xddxdd/dependabot/go_modules/proxy/github.com/spf13/pflag-1.0.7 2025-07-17 00:25:25 +00:00
dependabot[bot]
5b33629a9d build(deps): bump github.com/spf13/pflag from 1.0.6 to 1.0.7 in /proxy
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.6...v1.0.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-17 00:23:21 +00:00
dependabot[bot]
0868c5d42c Merge pull request #121 from xddxdd/dependabot/go_modules/frontend/github.com/spf13/pflag-1.0.7 2025-07-17 00:09:29 +00:00
dependabot[bot]
bc61579e6a build(deps): bump github.com/spf13/pflag in /frontend
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.6...v1.0.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-17 00:07:25 +00:00
10 changed files with 183 additions and 5787 deletions

View File

@@ -1 +1 @@
v1.3.10 v1.3.11

View File

@@ -1,33 +1,27 @@
module github.com/xddxdd/bird-lg-go/frontend module github.com/xddxdd/bird-lg-go/frontend
go 1.17 go 1.23.0
require ( require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/gorilla/handlers v1.5.2 github.com/gorilla/handlers v1.5.2
github.com/jarcoal/httpmock v1.4.0 github.com/jarcoal/httpmock v1.4.1
github.com/magiconair/properties v1.8.10 github.com/magiconair/properties v1.8.10
github.com/spf13/pflag v1.0.6 github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.21.0
) )
require ( require (
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/spf13/afero v1.15.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.10.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 github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect
go.uber.org/multierr v1.9.0 // indirect golang.org/x/sys v0.29.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/text v0.28.0 // 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
) )

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ type settingType struct {
domain string domain string
proxyPort int proxyPort int
whoisServer string whoisServer string
listen string listen []string
dnsInterface string dnsInterface string
netSpecificMode string netSpecificMode string
titleBrand string titleBrand string
@@ -35,24 +35,29 @@ func main() {
parseSettings() parseSettings()
ImportTemplates() ImportTemplates()
var l net.Listener for _, listenAddr := range setting.listen {
var err error go func(listenAddr string) {
var l net.Listener
var err error
if strings.HasPrefix(setting.listen, "/") { if strings.HasPrefix(listenAddr, "/") {
// Delete existing socket file, ignore errors (will fail later anyway) // Delete existing socket file, ignore errors (will fail later anyway)
os.Remove(setting.listen) os.Remove(listenAddr)
l, err = net.Listen("unix", setting.listen) l, err = net.Listen("unix", listenAddr)
} else { } else {
listenAddr := setting.listen if !strings.Contains(listenAddr, ":") {
if !strings.Contains(listenAddr, ":") { listenAddr = ":" + listenAddr
listenAddr = ":" + listenAddr }
} l, err = net.Listen("tcp", listenAddr)
l, err = net.Listen("tcp", listenAddr) }
if err != nil {
panic(err)
}
webServerStart(l)
}(listenAddr)
} }
if err != nil { select {}
panic(err)
}
webServerStart(l)
} }

View File

@@ -9,25 +9,25 @@ import (
) )
type viperSettingType struct { type viperSettingType struct {
Servers string `mapstructure:"servers"` Servers string `mapstructure:"servers"`
Domain string `mapstructure:"domain"` Domain string `mapstructure:"domain"`
ProxyPort int `mapstructure:"proxy_port"` ProxyPort int `mapstructure:"proxy_port"`
WhoisServer string `mapstructure:"whois"` WhoisServer string `mapstructure:"whois"`
Listen string `mapstructure:"listen"` Listen []string `mapstructure:"listen"`
DNSInterface string `mapstructure:"dns_interface"` DNSInterface string `mapstructure:"dns_interface"`
NetSpecificMode string `mapstructure:"net_specific_mode"` NetSpecificMode string `mapstructure:"net_specific_mode"`
TitleBrand string `mapstructure:"title_brand"` TitleBrand string `mapstructure:"title_brand"`
NavBarBrand string `mapstructure:"navbar_brand"` NavBarBrand string `mapstructure:"navbar_brand"`
NavBarBrandURL string `mapstructure:"navbar_brand_url"` NavBarBrandURL string `mapstructure:"navbar_brand_url"`
NavBarAllServer string `mapstructure:"navbar_all_servers"` NavBarAllServer string `mapstructure:"navbar_all_servers"`
NavBarAllURL string `mapstructure:"navbar_all_url"` NavBarAllURL string `mapstructure:"navbar_all_url"`
BgpmapInfo string `mapstructure:"bgpmap_info"` BgpmapInfo string `mapstructure:"bgpmap_info"`
TelegramBotName string `mapstructure:"telegram_bot_name"` TelegramBotName string `mapstructure:"telegram_bot_name"`
ProtocolFilter string `mapstructure:"protocol_filter"` ProtocolFilter string `mapstructure:"protocol_filter"`
NameFilter string `mapstructure:"name_filter"` NameFilter string `mapstructure:"name_filter"`
TimeOut int `mapstructure:"timeout"` TimeOut int `mapstructure:"timeout"`
ConnectionTimeOut int `mapstructure:"connection_timeout"` ConnectionTimeOut int `mapstructure:"connection_timeout"`
TrustProxyHeaders bool `mapstructure:"trust_proxy_headers"` TrustProxyHeaders bool `mapstructure:"trust_proxy_headers"`
} }
// Parse settings with viper, and convert to legacy setting format // Parse settings with viper, and convert to legacy setting format
@@ -52,7 +52,7 @@ func parseSettings() {
pflag.String("whois", "whois.verisign-grs.com", "whois server for queries") pflag.String("whois", "whois.verisign-grs.com", "whois server for queries")
viper.BindPFlag("whois", pflag.Lookup("whois")) viper.BindPFlag("whois", pflag.Lookup("whois"))
pflag.String("listen", "5000", "address or unix socket bird-lg is listening on") pflag.StringSlice("listen", []string{"5000"}, "address or unix socket bird-lg is listening on")
viper.BindPFlag("listen", pflag.Lookup("listen")) viper.BindPFlag("listen", pflag.Lookup("listen"))
pflag.String("dns-interface", "asn.cymru.com", "dns zone to query ASN information") pflag.String("dns-interface", "asn.cymru.com", "dns zone to query ASN information")

View File

@@ -12,6 +12,7 @@ import (
"net/url" "net/url"
"os" "os"
"strings" "strings"
"sync/atomic"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
) )
@@ -39,8 +40,10 @@ var primitiveMap = map[string]string{
"traceroute": "%s", "traceroute": "%s",
} }
var webServerPrepared uint32 = 0
// serve up a generic error // serve up a generic error
func serverError(w http.ResponseWriter, r *http.Request) { func serverError(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("500 Internal Server Error")) w.Write([]byte("500 Internal Server Error"))
} }
@@ -192,11 +195,11 @@ func webHandlerBGPMap(endpoint string, command string) func(w http.ResponseWrite
} }
} }
// set up routing paths and start webserver // set up routing paths
func webServerStart(l net.Listener) { func webServerPrepare() {
// redirect main page to all server summary // redirect main page to all server summary
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/summary/"+url.PathEscape(strings.Join(setting.servers, "+")), 302) http.Redirect(w, r, "/summary/"+url.PathEscape(strings.Join(setting.servers, "+")), http.StatusFound)
}) })
// serve static pages using embedded assets from template.go // serve static pages using embedded assets from template.go
@@ -235,8 +238,14 @@ func webServerStart(l net.Listener) {
http.HandleFunc("/whois/", webHandlerWhois) http.HandleFunc("/whois/", webHandlerWhois)
http.HandleFunc("/api/", apiHandler) http.HandleFunc("/api/", apiHandler)
http.HandleFunc("/telegram/", webHandlerTelegramBot) http.HandleFunc("/telegram/", webHandlerTelegramBot)
}
// start webserver
func webServerStart(l net.Listener) {
if atomic.SwapUint32(&webServerPrepared, 1) == 0 {
webServerPrepare()
}
// Start HTTP server
var handler http.Handler var handler http.Handler
handler = http.DefaultServeMux handler = http.DefaultServeMux
if setting.trustProxyHeaders { if setting.trustProxyHeaders {

View File

@@ -1,32 +1,26 @@
module github.com/xddxdd/bird-lg-go/proxy module github.com/xddxdd/bird-lg-go/proxy
go 1.17 go 1.23.0
require ( require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/gorilla/handlers v1.5.2 github.com/gorilla/handlers v1.5.2
github.com/magiconair/properties v1.8.10 github.com/magiconair/properties v1.8.10
github.com/spf13/pflag v1.0.6 github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.21.0
) )
require ( require (
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/spf13/afero v1.15.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.10.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 github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect
go.uber.org/multierr v1.9.0 // indirect golang.org/x/sys v0.29.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/text v0.28.0 // 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
) )

File diff suppressed because it is too large Load Diff

View File

@@ -62,7 +62,7 @@ func accessHandler(next http.Handler) http.Handler {
type settingType struct { type settingType struct {
birdSocket string birdSocket string
listen string listen []string
allowedNets []*net.IPNet allowedNets []*net.IPNet
tr_bin string tr_bin string
tr_flags []string tr_flags []string
@@ -76,32 +76,40 @@ func main() {
parseSettings() parseSettings()
tracerouteAutodetect() tracerouteAutodetect()
fmt.Printf("Listening on %s...\n", setting.listen) mux := http.NewServeMux()
var l net.Listener // Prepare HTTP server
var err error mux.HandleFunc("/", invalidHandler)
mux.HandleFunc("/bird", birdHandler)
mux.HandleFunc("/bird6", birdHandler)
mux.HandleFunc("/traceroute", tracerouteHandler)
mux.HandleFunc("/traceroute6", tracerouteHandler)
if strings.HasPrefix(setting.listen, "/") { for _, listenAddr := range setting.listen {
// Delete existing socket file, ignore errors (will fail later anyway) go func(addr string) {
os.Remove(setting.listen) fmt.Printf("Listening on %s...\n", addr)
l, err = net.Listen("unix", setting.listen)
} else { var l net.Listener
listenAddr := setting.listen var err error
if !strings.Contains(listenAddr, ":") {
listenAddr = ":" + listenAddr if strings.HasPrefix(addr, "/") {
} // Delete existing socket file, ignore errors (will fail later anyway)
l, err = net.Listen("tcp", listenAddr) os.Remove(addr)
l, err = net.Listen("unix", addr)
} else {
if !strings.Contains(addr, ":") {
addr = ":" + addr
}
l, err = net.Listen("tcp", addr)
}
if err != nil {
panic(err)
}
http.Serve(l, handlers.LoggingHandler(os.Stdout, accessHandler(mux)))
}(listenAddr)
} }
if err != nil { select {}
panic(err)
}
// Start HTTP server
http.HandleFunc("/", invalidHandler)
http.HandleFunc("/bird", birdHandler)
http.HandleFunc("/bird6", birdHandler)
http.HandleFunc("/traceroute", tracerouteHandler)
http.HandleFunc("/traceroute6", tracerouteHandler)
http.Serve(l, handlers.LoggingHandler(os.Stdout, accessHandler(http.DefaultServeMux)))
} }

View File

@@ -11,12 +11,12 @@ import (
) )
type viperSettingType struct { type viperSettingType struct {
BirdSocket string `mapstructure:"bird_socket"` BirdSocket string `mapstructure:"bird_socket"`
Listen string `mapstructure:"listen"` Listen []string `mapstructure:"listen"`
AllowedNets string `mapstructure:"allowed_ips"` AllowedNets string `mapstructure:"allowed_ips"`
TracerouteBin string `mapstructure:"traceroute_bin"` TracerouteBin string `mapstructure:"traceroute_bin"`
TracerouteFlags string `mapstructure:"traceroute_flags"` TracerouteFlags string `mapstructure:"traceroute_flags"`
TracerouteRaw bool `mapstructure:"traceroute_raw"` TracerouteRaw bool `mapstructure:"traceroute_raw"`
} }
// Parse settings with viper, and convert to legacy setting format // Parse settings with viper, and convert to legacy setting format
@@ -37,7 +37,7 @@ func parseSettings() {
pflag.String("bird", "/var/run/bird/bird.ctl", "socket file for bird, set either in parameter or environment variable BIRD_SOCKET") pflag.String("bird", "/var/run/bird/bird.ctl", "socket file for bird, set either in parameter or environment variable BIRD_SOCKET")
viper.BindPFlag("bird_socket", pflag.Lookup("bird")) viper.BindPFlag("bird_socket", pflag.Lookup("bird"))
pflag.String("listen", "8000", "listen address, set either in parameter or environment variable BIRDLG_PROXY_PORT") pflag.StringSlice("listen", []string{"8000"}, "listen address, set either in parameter or environment variable BIRDLG_PROXY_PORT")
viper.BindPFlag("listen", pflag.Lookup("listen")) viper.BindPFlag("listen", pflag.Lookup("listen"))
pflag.String("allowed", "", "IPs or networks 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.")