我正在使用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
})
}
它的边缘有点粗糙,但它的功能尽我所能。谢谢你的帮助!
答案 0 :(得分:2)
ListenAndServe
中的地址是服务器在运行的计算机上绑定到的地址。它不是某种ip白名单的东西。这允许您指定要绑定服务器的(网络)接口。
因此,如果此计算机的以太网卡(ifconfig
)具有ipadress 10.0.100.100
,则可以将ListenAndServe
绑定到10.0.100.100:8123
。
无ip版本:8123
将服务器绑定到所有可用接口。例如。 [::]:8123
(netstat -l
),因此可以从外部访问。
为了得到你想要的东西你有几个选择:
ListenAndServe
您计算机上该子网的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
。