dreamworld2007 2016-06-18 12:26
浏览 263

使用golang http软件包时如何限制客户端IP地址

I'm using golang http package. How could the server limit client IP address?

func (s *Worker) Run(c chan error) {
    apiMux := http.NewServeMux()
    apiMux.HandleFunc("/test", s.test)
    apiMux.HandleFunc("/block/create", s.CreateBlock)
    apiMux.HandleFunc("/block/delete", s.DeleteBlock)

    apiServer := &http.Server{
        Addr:    "0.0.0.0:" + strconv.Itoa(s.ListenPort),
        Handler: apiMux,
    }

    go func() {
        log.Println("Worker listening on " + apiServer.Addr)
        c <- apiServer.ListenAndServe()
    }()
}
  • 写回答

1条回答 默认 最新

  • donglun4682 2016-06-18 12:59
    关注

    You need to do two things: one is to wrap your mux with a middleware handler that pre-processes your requests and validates the IP. The other is get the real IP of the user, which is important if you are behind a firewall or load balancer (resulting in the address being always that of the LB), or if your user is behind a proxy.

    As for wrapping your mux, it's pretty simple:

    apiServer := &http.Server{
        Addr:    "0.0.0.0:8080",
        Handler: http.HandlerFunc( func(w http.ResponseWriter, req *http.Request) {
            // get the real IP of the user, see below
            addr := getRealAddr(req)
    
           // the actual vaildation - replace with whatever you want
           if (addr != "1.2.3.4") {
                http.Error(w, "Blocked", 401)
                return
            }
            // pass the request to the mux
            apiMux.ServeHTTP(w,req)
        }),
    }
    

    And I'm attaching the getRealAddr function which is from an actual project in which I did something like this:

    func getRealAddr(r *http.Request)  string {
    
        remoteIP := ""
        // the default is the originating ip. but we try to find better options because this is almost
        // never the right IP
        if parts := strings.Split(r.RemoteAddr, ":"); len(parts) == 2 {
            remoteIP = parts[0]
        }
        // If we have a forwarded-for header, take the address from there
        if xff := strings.Trim(r.Header.Get("X-Forwarded-For"), ","); len(xff) > 0 {
            addrs := strings.Split(xff, ",")
            lastFwd := addrs[len(addrs)-1]
            if ip := net.ParseIP(lastFwd); ip != nil {
                remoteIP = ip.String()
            }
        // parse X-Real-Ip header
        } else if xri := r.Header.Get("X-Real-Ip"); len(xri) > 0 {
            if ip := net.ParseIP(xri); ip != nil {
                remoteIP = ip.String()
            }
        }
    
        return remoteIP
    
    }
    

    As for the filtering, it can be based on a set of ips, or CIDR ranges, it's up to you of course.

    If you're interested, the above code is from an API building toolkit I wrote and used called Vertex, which has this built in: https://github.com/EverythingMe/vertex

    评论

报告相同问题?

悬赏问题

  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 个人网站被恶意大量访问,怎么办
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制