Golang : Identifying Golang HTTP client request
Problem:
You've read about the Mirai DDoS malware that infects IoT devices and turning them into a massive botnet. You're developing a new server program for collecting data from your IoT devices(clients) with Golang on HTTP protocol rather than MQTT. (but why!? - oh WiFI instead of Bluetooth)
To secure the devices, you change the factory default usernames and passwords upon unpacking/setup stage. Great!
For added security, you want to eliminate unwanted connections from potential malware or some random HTTP requests such as from browsers, you also want your program to accept valid connection from Golang client program only. How to identify a connection make by another Golang client?
NOTES:
1) This tutorial is written "for" a friend.
2)This is not a foolproof solution, but good enough to be used in early stage of requests filtering. A malicious coder can still spoof the user agent. For better security, consider implementing authentication mechanism with HMAC. See https://www.socketloop.com/tutorials/golang-simple-client-server-hmac-authentication-without-ssl-example.
3)The potential problem is that .... you might have to hard code the HMAC's secret key in your program.
SOLUTION:
Check the user agent string in the request header. If the user agent starts with Go-http
, you can be certain that the request is made by a Golang program.
GET / HTTP/1.1
User-Agent [Go-http-client/1.1] <------- here
Accept-Encoding [gzip]
Detected IP address is : 46.166.190.130:3619
Real IP address could be :
Go HTTP client detected <---------- and here
Here is the code example that you can use to identify Golang HTTP client request. Run the code and visit the server with another Golang HTTP client. You might want to do an anonymous visit via Tor network as well. See https://www.socketloop.com/tutorials/golang-accessing-content-anonymously-with-tor
Here you go!
package main
import (
"fmt"
"net/http"
"strings"
)
func checkRequest(w http.ResponseWriter, r *http.Request) {
// similar to PHP's $_SERVER["REQUEST_METHOD"], $_SERVER["REQUEST_URI"] & $_SERVER["REQUEST_PROTOCOL"]
basicInfo := r.Method + " " + r.RequestURI + " " + r.Proto
fmt.Println(basicInfo)
// some extra header information
headerInfo := r.Header
for key, value := range headerInfo {
fmt.Println(key, value)
}
// similar to $_SERVER["REMOTE_ADDR"]
fmt.Println("Detected IP address is : ", r.RemoteAddr)
// in case request is via proxy server
fmt.Println("Real IP address could be : ", r.Header.Get("X-Forwarded-For"))
if strings.HasPrefix(r.Header.Get("User-Agent"), "Go-http-client") {
fmt.Println("Go HTTP client detected")
// then continue to process request or perform HMAC authentication
// else ignore or block further request from the originating IP address.
}
fmt.Println("-------------------------------------------------------")
}
func main() {
http.HandleFunc("/", checkRequest)
http.ListenAndServe(":8080", nil)
}
Happy coding!
References:
https://www.socketloop.com/tutorials/golang-accessing-content-anonymously-with-tor
http://www.darknet.org.uk/2016/10/mirai-ddos-malware-source-code-leaked/
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+7.8k Golang : Auto-generate reply email with text/template package
+14.2k Golang : Missing Bazaar command
+5.5k Golang : List all packages and search for certain package
+51.6k Golang : How to get struct field and value by name
+9k Golang : Terminate-stay-resident or daemonize your program?
+5.4k Golang : Find change in a combination of coins example
+6k Unix/Linux : Use netstat to find out IP addresses served by your website server
+22.4k Golang : Calculate time different
+4.4k Linux/MacOSX : How to symlink a file?
+10.2k Golang : Interfacing with PayPal's IPN(Instant Payment Notification) example
+7.7k Golang : Variadic function arguments sanity check example
+13.2k Golang : Convert spaces to tabs and back to spaces example