feat: add legacy IP access filtering
This commit is contained in:
@@ -63,7 +63,7 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
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)
|
addr := ":" + itoa(cfg.Port)
|
||||||
log.Printf("chfs-ng listening on %s root=%s", addr, filepath.Clean(root))
|
log.Printf("chfs-ng listening on %s root=%s", addr, filepath.Clean(root))
|
||||||
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -22,6 +23,7 @@ type Server struct {
|
|||||||
Auth *auth.Manager
|
Auth *auth.Manager
|
||||||
Sessions map[string]*auth.Account
|
Sessions map[string]*auth.Account
|
||||||
WebDAVRoot string
|
WebDAVRoot string
|
||||||
|
Allow string
|
||||||
}
|
}
|
||||||
type fileInfo struct {
|
type fileInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -53,7 +55,7 @@ func (s *Server) Handler() http.Handler {
|
|||||||
mux.HandleFunc("/chfs/shared", s.shared)
|
mux.HandleFunc("/chfs/shared", s.shared)
|
||||||
mux.HandleFunc("/chfs/preview", s.preview)
|
mux.HandleFunc("/chfs/preview", s.preview)
|
||||||
mux.HandleFunc("/", s.fileHandler)
|
mux.HandleFunc("/", s.fileHandler)
|
||||||
return mux
|
return s.ipFilter(mux)
|
||||||
}
|
}
|
||||||
func account(r *http.Request, s *Server) *auth.Account {
|
func account(r *http.Request, s *Server) *auth.Account {
|
||||||
if c, e := r.Cookie("chfs_token"); e == nil {
|
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 := &webdav.Handler{FileSystem: webdav.LocalFileSystem(s.WebDAVRoot)}
|
||||||
h.ServeHTTP(w, r)
|
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