feat: add legacy IP access filtering
This commit is contained in:
@@ -63,7 +63,7 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
srv := &api.Server{Store: storage.Local{Root: root}, Auth: mgr, Sessions: map[string]*auth.Account{}, WebDAVRoot: root}
|
||||
srv := &api.Server{Store: storage.Local{Root: root}, Auth: mgr, Sessions: map[string]*auth.Account{}, WebDAVRoot: root, Allow: cfg.Allow}
|
||||
addr := ":" + itoa(cfg.Port)
|
||||
log.Printf("chfs-ng listening on %s root=%s", addr, filepath.Clean(root))
|
||||
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@@ -22,6 +23,7 @@ type Server struct {
|
||||
Auth *auth.Manager
|
||||
Sessions map[string]*auth.Account
|
||||
WebDAVRoot string
|
||||
Allow string
|
||||
}
|
||||
type fileInfo struct {
|
||||
Name string `json:"name"`
|
||||
@@ -53,7 +55,7 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("/chfs/shared", s.shared)
|
||||
mux.HandleFunc("/chfs/preview", s.preview)
|
||||
mux.HandleFunc("/", s.fileHandler)
|
||||
return mux
|
||||
return s.ipFilter(mux)
|
||||
}
|
||||
func account(r *http.Request, s *Server) *auth.Account {
|
||||
if c, e := r.Cookie("chfs_token"); e == nil {
|
||||
@@ -509,3 +511,78 @@ func (s *Server) webdav(w http.ResponseWriter, r *http.Request) {
|
||||
h := &webdav.Handler{FileSystem: webdav.LocalFileSystem(s.WebDAVRoot)}
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (s *Server) ipFilter(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if s.Allow != "" && !allowedIP(s.Allow, clientIP(r)) {
|
||||
http.Error(w, "forbidden", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func clientIP(r *http.Request) net.IP {
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err == nil {
|
||||
return net.ParseIP(host)
|
||||
}
|
||||
return net.ParseIP(r.RemoteAddr)
|
||||
}
|
||||
|
||||
func allowedIP(rule string, ip net.IP) bool {
|
||||
if ip == nil {
|
||||
return false
|
||||
}
|
||||
rule = strings.TrimSpace(rule)
|
||||
black := false
|
||||
if strings.HasPrefix(strings.ToLower(rule), "not(") && strings.HasSuffix(rule, ")") {
|
||||
black = true
|
||||
rule = strings.TrimSpace(rule[4 : len(rule)-1])
|
||||
}
|
||||
matched := false
|
||||
for _, item := range strings.Split(rule, ",") {
|
||||
item = strings.TrimSpace(item)
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
if ipInItem(ip, item) {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if black {
|
||||
return !matched
|
||||
}
|
||||
return matched
|
||||
}
|
||||
|
||||
func ipInItem(ip net.IP, item string) bool {
|
||||
if strings.Contains(item, "-") {
|
||||
parts := strings.SplitN(item, "-", 2)
|
||||
lo, hi := net.ParseIP(strings.TrimSpace(parts[0])), net.ParseIP(strings.TrimSpace(parts[1]))
|
||||
if lo == nil || hi == nil {
|
||||
return false
|
||||
}
|
||||
v := ip.To4()
|
||||
l := lo.To4()
|
||||
h := hi.To4()
|
||||
if v == nil || l == nil || h == nil {
|
||||
return false
|
||||
}
|
||||
return bytesCompare(v, l) >= 0 && bytesCompare(v, h) <= 0
|
||||
}
|
||||
return ip.Equal(net.ParseIP(item))
|
||||
}
|
||||
|
||||
func bytesCompare(a, b net.IP) int {
|
||||
for i := range a {
|
||||
if a[i] < b[i] {
|
||||
return -1
|
||||
}
|
||||
if a[i] > b[i] {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user