From 1d478bef0a3949c6ce948a00e5b47bd9d717d806 Mon Sep 17 00:00:00 2001 From: starainrt Date: Tue, 7 May 2024 13:06:15 +0800 Subject: [PATCH] http server security improve --- dfinder/dfinder.go | 2 +- httpserver/cmd.go | 3 ++ httpserver/server.go | 91 ++++++++++++++++++++++++++++++++++++-------- main.go | 2 +- 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/dfinder/dfinder.go b/dfinder/dfinder.go index 118a4f4..6367ec2 100644 --- a/dfinder/dfinder.go +++ b/dfinder/dfinder.go @@ -79,7 +79,7 @@ func fileFinder(path string, reg string, onlyFilterName bool, outpath string, sh } return "" } - fp := new(os.File) + var fp *os.File if outpath != "" { fp, err = os.Create(outpath) if err != nil { diff --git a/httpserver/cmd.go b/httpserver/cmd.go index d23a97c..7810fa9 100644 --- a/httpserver/cmd.go +++ b/httpserver/cmd.go @@ -30,6 +30,9 @@ func init() { Cmd.Flags().StringVarP(&s.key, "ssl-key", "k", "", "TLS密钥路径") Cmd.Flags().BoolVarP(&s.disableMIME, "disablemime", "m", false, "停止解析MIME,全部按下载文件处理") Cmd.Flags().StringSliceVarP(&s.protectAuthPage, "protect-page", "P", []string{}, "Basic Auth 开启白名单") + Cmd.Flags().StringVar(&s.page401, "401", "", "自定义401页面地址") + Cmd.Flags().StringVar(&s.page403, "403", "", "自定义403页面地址") + Cmd.Flags().StringVar(&s.page404, "404", "", "自定义404页面地址") Cmd.Flags().Bool("daeapplied", false, "") Cmd.Flags().MarkHidden("daeapplied") } diff --git a/httpserver/server.go b/httpserver/server.go index 5e9dfb7..d9684ca 100644 --- a/httpserver/server.go +++ b/httpserver/server.go @@ -37,6 +37,9 @@ type HttpServerCfg struct { key string addr string port string + page404 string + page403 string + page401 string protectAuthPage []string disableMIME bool ctx context.Context @@ -338,15 +341,27 @@ func (h *HttpServer) Run(ctx context.Context) error { if strings.Contains(v.Flags.String(), "up") { addrs, err := v.Addrs() if err == nil { - var ips []string for _, ip := range addrs { - ips = append(ips, ip.String()) + starlog.Cyan("Name:%s\tIP:%s\n", v.Name, ip) } - starlog.Noticef("Name:%s IP:%s MAC:%s\n", v.Name, strings.Join(ips, ","), v.HardwareAddr) } } } } + h.envPath, err = filepath.Abs(h.envPath) + if err != nil { + starlog.Errorln("Failed to get abs path of", h.envPath) + return err + } + uconn, err := net.Dial("udp", "106.55.44.79:80") + if err == nil { + schema := "http://" + if h.cert != "" { + schema = "https://" + } + starlog.Infof("Visit: %s%s:%s\n", schema, uconn.LocalAddr().(*net.UDPAddr).IP.String(), h.port) + uconn.Close() + } starlog.Infoln("Listening on " + h.addr + ":" + h.port) if h.cert == "" { if err := server.ListenAndServe(); err != http.ErrServerClosed { @@ -364,9 +379,39 @@ func (h *HttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.Listen(w, r) } -func (h *HttpServer) GiveBasicAuth(w http.ResponseWriter) { - w.Header().Set("WWW-Authenticate", ` Basic realm="Please Enter Passwd"`) +func (h *HttpServer) Page404(w http.ResponseWriter) { + w.WriteHeader(404) + if h.page404 != "" { + data, err := os.ReadFile(h.page404) + if err == nil { + w.Write(data) + return + } + } + w.Write([]byte(`B612 Http Server

404 NOT FOUND


`)) +} + +func (h *HttpServer) Page403(w http.ResponseWriter) { + w.WriteHeader(403) + if h.page403 != "" { + data, err := os.ReadFile(h.page403) + if err == nil { + w.Write(data) + return + } + } + w.Write([]byte(`B612 Http Server

403 Forbidden


`)) +} + +func (h *HttpServer) Page401(w http.ResponseWriter) { w.WriteHeader(401) + if h.page401 != "" { + data, err := os.ReadFile(h.page401) + if err == nil { + w.Write(data) + return + } + } w.Write([]byte(` 401 Authorization Required @@ -377,6 +422,11 @@ func (h *HttpServer) GiveBasicAuth(w http.ResponseWriter) { `)) } +func (h *HttpServer) GiveBasicAuth(w http.ResponseWriter) { + w.Header().Set("WWW-Authenticate", ` Basic realm="Please Enter Passwd"`) + h.Page401(w) +} + func (h *HttpServer) BasicAuth(log *starlog.StarLogger, w http.ResponseWriter, r *http.Request) bool { if h.basicAuthPwd != "" { if len(h.protectAuthPage) != 0 { @@ -429,6 +479,8 @@ func (h *HttpServer) SetUpload(w http.ResponseWriter, r *http.Request, path stri } func (h *HttpServer) Listen(w http.ResponseWriter, r *http.Request) { log := starlog.Std.NewFlag() + log.SetShowFuncName(false) + log.SetShowOriginFile(false) w.Header().Set("X-Powered-By", "B612.ME") w.Header().Set("Server", "B612/"+version) if !h.BasicAuth(log, w, r) { @@ -439,14 +491,24 @@ func (h *HttpServer) Listen(w http.ResponseWriter, r *http.Request) { h.uploadFile(w, r) return } - fullpath := filepath.Join(h.envPath, path) + ua := r.Header.Get("User-Agent") + fullpath := filepath.Clean(filepath.Join(h.envPath, path)) + + { + //security check + if fullpath != h.envPath && !strings.HasPrefix(fullpath, h.envPath) { + log.Warningf("Invalid Path %s IP:%s Fullpath:%s\n", path, r.RemoteAddr, fullpath) + h.Page403(w) + return + } + } if h.indexFile != "" && staros.IsFolder(fullpath) { if staros.Exists(filepath.Join(fullpath, h.indexFile)) { fullpath = filepath.Join(fullpath, h.indexFile) path = filepath.Join(path, h.indexFile) } } - log.Noticef("Start Method:%s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr) + now := time.Now() if h.SetUpload(w, r, path) { return } @@ -454,9 +516,9 @@ func (h *HttpServer) Listen(w http.ResponseWriter, r *http.Request) { case "OPTIONS", "HEAD": err := h.BuildHeader(w, r, fullpath) if err != nil { - log.Warningf("Finished Method:%s Path:%s IP:%s Err:%v\n", r.Method, path, r.RemoteAddr, err) + log.Warningf("%s %s From %s %s %.2fs %v\n", r.Method, path, r.RemoteAddr, ua, time.Since(now).Seconds(), err) } else { - log.Infof("Finished Method:%s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr) + log.Infof("%s %s From %s %s %.2fs \n", r.Method, path, r.RemoteAddr, ua, time.Since(now).Seconds()) } case "GET": err := h.BuildHeader(w, r, fullpath) @@ -465,12 +527,12 @@ func (h *HttpServer) Listen(w http.ResponseWriter, r *http.Request) { } err = h.ResponseGet(log, w, r, fullpath) if err != nil { - log.Warningf("Finished Method %s Path:%s IP:%s Err:%v\n", r.Method, path, r.RemoteAddr, err) + log.Warningf("%s %s From %s %s %.2fs %v\n", r.Method, path, r.RemoteAddr, ua, time.Since(now).Seconds(), err) return } - log.Infof("Finished Method:%s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr) + log.Infof("%s %s From %s %s %.2fs \n", r.Method, path, r.RemoteAddr, ua, time.Since(now).Seconds()) default: - log.Warningf("Invalid Method %s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr) + log.Errorf("Invalid %s %s From %s %s %.2fs %v\n", r.Method, path, r.RemoteAddr, ua, time.Since(now).Seconds()) return } } @@ -619,8 +681,7 @@ func (h *HttpServer) getFolder(log *starlog.StarLogger, w http.ResponseWriter, r func (h *HttpServer) getFile(log *starlog.StarLogger, w http.ResponseWriter, r *http.Request, fullpath string) error { if !staros.Exists(fullpath) { - w.WriteHeader(404) - w.Write([]byte(`B612 Http Server

404 NOT FOUND


`)) + h.Page404(w) return errors.New("File Not Found! 404 ERROR") } //starlog.Debugln(r.Header) @@ -711,7 +772,7 @@ func (h *HttpServer) getFile(log *starlog.StarLogger, w http.ResponseWriter, r * } return nil } - log.Debugf("206 transfer mode for %v %v\n", r.URL.Path, r.RemoteAddr) + log.Debugf("206 transfer mode for %v %v start %v end %v\n", r.URL.Path, r.RemoteAddr, startRange, endRange) w.WriteHeader(206) fp.Seek(int64(startRange), 0) count := startRange diff --git a/main.go b/main.go index ad98e4d..06c1618 100644 --- a/main.go +++ b/main.go @@ -41,7 +41,7 @@ import ( var cmdRoot = &cobra.Command{ Use: "b612", - Version: "2.1.0.beta.6", + Version: "2.1.0.beta.8", } func init() {