限制从本地子网访问GO Web服务到客户端

时间:2014-09-30 09:58:50

标签: http go

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

我尝试使用子网掩码作为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
    })
}

它的边缘有点粗糙,但它的功能尽我所能。谢谢你的帮助!

3 个答案:

答案 0 :(得分:2)

ListenAndServe中的地址是服务器在运行的计算机上绑定到的地址。它不是某种ip白名单的东西。这允许您指定要绑定服务器的(网络)接口。

因此,如果此计算机的以太网卡(ifconfig)具有ipadress 10.0.100.100,则可以将ListenAndServe绑定到10.0.100.100:8123。 无ip版本:8123将服务器绑定到所有可用接口。例如。 [::]:8123netstat -l),因此可以从外部访问。

为了得到你想要的东西你有几个选择:

  • 将您的机器放在您信任的私有子网中并绑定ListenAndServe 您计算机上该子网的IP。因此,它只能从该子网内路由。
  • 在此服务器前使用网络服务器,让它向其发送请求 基于其ip acl(例如nginx
  • 在go服务器代码中实现您自己的ip(范围)过滤(例如,使用request.URL并针对您的白名单进行测试)

答案 1 :(得分:1)

编写一个处理程序,在委托给另一个处理程序之前检查是否允许客户端的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))

注意:我输入上面的代码而没有编译或测试它。在解析和测试远程地址时可能需要进行一些调整。

答案 2 :(得分:0)

您可以在多个端口/主机上侦听,您必须多次呼叫ListenAndServe

func main() {
    addrs := []string{"127.0.0.1:8080", "10.0.0.1:8080", "172.16.0.1:8080", "192.168.0.1:8080", "192.168.1.1:8080"}
    errs := make(chan error)
    for _, addr := range addrs {
        go func(addr string) {
            errs <- http.ListenAndServe(addr, nil) //or replace the nil with your mux
        }(addr)
    }
    i := len(addrs)
    for err := range errs {
        fmt.Println(err)
        if i = i - 1; i == 0 {
            break
        }
    }
}

或者你可以使用nging,只需让你的服务器听127.0.0.1