我仅使用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/