我仅使用GO http包在GO中编写了一个小型Web服务。我想将对Web服务的访问限制为本地子网上的客户端(127.0.0.1、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)。

我尝试使用子网掩码作为ListenAndServe的addr参数,但退出时出现“无此类主机”错误。

编辑:

这是我在@RickA和@Dewy Broto的帮助下提出的解决方案。

func JustLocal(handler http.Handler) http.Handler {
    var local_subnets []*net.IPNet
    local_subnet_s := []string{"127.0.0.1/31", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"}

    for _,net_s := range local_subnet_s {
        _, n, _ := net.ParseCIDR(net_s)
        local_subnets = append(local_subnets, n)
    }

    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println(r.RemoteAddr)
        remote_ip := net.ParseIP(strings.Split(r.RemoteAddr, ":")[0])
        fmt.Println(remote_ip)

        local := false
        for _, local_subnet := range local_subnets {
            fmt.Println(local_subnet, remote_ip)
            if local_subnet.Contains(remote_ip) {
                local = true
                break
            }
        }
        if !local {
            http.Error(w, "go away", 403)
            return
        }
        handler.ServeHTTP(w, r)
        return
    })
}

边缘有点生,但据我所知它仍然有效。感谢您的所有帮助!

最佳答案

编写一个处理程序,在委派给另一个处理程序之前检查该客户端的IP地址是否被允许:

type authorizationHandler struct {
    nets []*net.IPNet
    h handler
}

func (ah *authorizationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    ok := false
    ip := net.ParseIP(r.RemoteAddr)
    for _, n := range ah.nets {
       if n.Contains(ip) {
         ok := true
         break
       }
    }
    if !ok {
       http.Error(w, "go away", 403)
       return
    }
    ah.h(w, r)
}

使用此处理程序包装您的根处理程序:
err := ListenAndServe(addr,
          &authorizationHandler{nets: allowedNets, h:rootHandler))

注意:我没有编辑或测试就输入了上面的代码。可能需要对解析和测试远程地址进行一些调整。

关于http - 限制来自本地子网的客户端对GO Web服务的访问,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26117940/

10-16 18:38