impl cidr as password:CIDR:http://target

This commit is contained in:
bel
2025-11-20 08:28:25 -07:00
parent 9791f80b28
commit 2ff12869cd
6 changed files with 88 additions and 2 deletions

View File

@@ -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,
})
}