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()
}()
}
The http package in GoLang allows HTTP functions to be carried out in GoLang scripts.
The docs: "PostForm issues a POST to the specified URL, with data's keys and values URL-encoded as the request body. The Content-Type header is set to application/x-www-form-urlencoded ."
Go can be also used to create web applications. Net/http is a library package used to build web applications. It has HandelFunc() function which routes the incoming request to its corresponding function. The ListenAndServe function is used to create a resource server which listens to the provided port.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With