impl cidr as password:CIDR:http://target
parent
9791f80b28
commit
2ff12869cd
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
type Proxy struct {
|
||||
Auth string
|
||||
From string
|
||||
To string
|
||||
}
|
||||
|
||||
|
|
@ -60,14 +61,15 @@ func GetRoutes() map[string]Proxy {
|
|||
s := conf.Get("proxy2").GetString()
|
||||
var dict map[string]string
|
||||
if err := yaml.Unmarshal([]byte(s), &dict); err == nil && len(s) > 0 {
|
||||
pattern := regexp.MustCompile(`(([^:]*):)?([a-z0-9]*:.*)`)
|
||||
pattern := regexp.MustCompile(`(([^:]*):)?(([^:]*):)?([a-z0-9]*:.*)`)
|
||||
result := map[string]Proxy{}
|
||||
for k, v := range dict {
|
||||
submatches := pattern.FindAllStringSubmatch(v, -1)
|
||||
log.Printf("%+v", submatches)
|
||||
result[k] = Proxy{
|
||||
Auth: submatches[0][2],
|
||||
To: submatches[0][3],
|
||||
From: submatches[0][4],
|
||||
To: submatches[0][5],
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -13,5 +13,6 @@ require gopkg.in/yaml.v2 v2.4.0
|
|||
|
||||
require (
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/yl2chen/cidranger v1.0.2 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
)
|
||||
|
|
|
|||
7
go.sum
7
go.sum
|
|
@ -2,6 +2,7 @@ gitea.inhome.blapointe.com/local/args v0.0.0-20240109214601-658deda479a4 h1:4qBH
|
|||
gitea.inhome.blapointe.com/local/args v0.0.0-20240109214601-658deda479a4/go.mod h1:SqCOE3bE3wvrztVIQGHuyxHKfDjRKU9EWhBdkmkiwyc=
|
||||
gitea.inhome.blapointe.com/local/logb v0.0.0-20231109150430-1221d87a6dbc h1:u3akQkq12V8xWXlcDgjZxIK6hqo6f1eHd9KOxAKMoKc=
|
||||
gitea.inhome.blapointe.com/local/logb v0.0.0-20231109150430-1221d87a6dbc/go.mod h1:KwilawX4UgD4HxSJAVFEzkuckrnHeQrd49KwUX6GpYU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
|
|
@ -9,10 +10,16 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
|
||||
github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ func (s *Server) lookupAuth(host string) (string, error) {
|
|||
return v.String(), err
|
||||
}
|
||||
|
||||
func (s *Server) lookupFrom(host string) (string, error) {
|
||||
v := packable.NewString()
|
||||
err := s.db.Get(nsRouting, host+"//from", v)
|
||||
return v.String(), err
|
||||
}
|
||||
|
||||
func mapKey(host string) string {
|
||||
host = strings.Split(host, ".")[0]
|
||||
host = strings.Split(host, ":")[0]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -62,6 +63,9 @@ func (s *Server) Route(src string, dst config.Proxy) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.db.Set(nsRouting, src+"//from", packable.NewString(dst.From)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.db.Set(nsRouting, src+"//auth", packable.NewString(dst.Auth)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -167,12 +171,44 @@ func (s *Server) Pre(foo http.HandlerFunc) http.HandlerFunc {
|
|||
log.Printf("failed to auth: expected %q but got %q", auth, p)
|
||||
w.Header().Set("WWW-Authenticate", "Basic")
|
||||
http.Error(w, "unexpected basic auth", http.StatusUnauthorized)
|
||||
} else if from, err := s.lookupFrom(mapKey(r.Host)); err != nil {
|
||||
log.Printf("failed to lookup from for %s (%s): %v", r.Host, mapKey(r.Host), err)
|
||||
http.Error(w, err.Error(), http.StatusBadGateway)
|
||||
} else if err := assertFrom(from, r.RemoteAddr); err != nil {
|
||||
log.Printf("failed to from: expected %q but got %q: %v", from, r.RemoteAddr, err)
|
||||
http.Error(w, "unexpected from", http.StatusUnauthorized)
|
||||
} else {
|
||||
foo(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertFrom(from, remoteAddr string) error {
|
||||
if from == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
pattern := regexp.MustCompile(`[0-9](:[0-9]+)$`).FindStringSubmatchIndex(remoteAddr)
|
||||
if len(pattern) == 4 {
|
||||
remoteAddr = remoteAddr[:pattern[2]]
|
||||
}
|
||||
|
||||
remoteIP := net.ParseIP(remoteAddr)
|
||||
if remoteIP == nil {
|
||||
return fmt.Errorf("cannot parse remote %q", remoteAddr)
|
||||
}
|
||||
|
||||
_, net, err := net.ParseCIDR(from)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if net.Contains(remoteIP) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("expected like %q but got like %q", from, remoteAddr)
|
||||
}
|
||||
|
||||
func withMeta(w http.ResponseWriter, r *http.Request) (*http.Request, func()) {
|
||||
meta := map[string]string{
|
||||
"ts": strconv.FormatInt(time.Now().Unix(), 10),
|
||||
|
|
@ -212,14 +248,19 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
func (s *Server) List(w http.ResponseWriter) {
|
||||
keys := s.db.Keys(nsRouting)
|
||||
hostURL := map[string]string{}
|
||||
hostFrom := map[string]string{}
|
||||
for _, key := range keys {
|
||||
u, _ := s.lookup(key)
|
||||
if u != nil && strings.TrimSuffix(key, "//auth") == key {
|
||||
hostURL[key] = u.String()
|
||||
}
|
||||
if u != nil && strings.TrimSuffix(key, "//from") == key {
|
||||
hostFrom[key] = u.String()
|
||||
}
|
||||
}
|
||||
json.NewEncoder(w).Encode(map[string]any{
|
||||
"hostsToURLs": hostURL,
|
||||
"hostsToFrom": hostFrom,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,3 +105,32 @@ func TestCORS(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAssertFrom(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
from string
|
||||
remote string
|
||||
err bool
|
||||
}{
|
||||
"empty": {},
|
||||
"ipv6 localhost": {
|
||||
from: "::1/128",
|
||||
remote: "::1:12345",
|
||||
},
|
||||
"ipv4 localhost": {
|
||||
from: "127.0.0.1/32",
|
||||
remote: "127.0.0.1:12345",
|
||||
},
|
||||
}
|
||||
|
||||
for name, d := range cases {
|
||||
c := d
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := assertFrom(c.from, c.remote)
|
||||
got := err != nil
|
||||
if got != c.err {
|
||||
t.Errorf("expected err=%v but got %v", c.err, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue