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
+15.6k Golang : Read a file line by line
+13.9k Golang : Convert IP version 6 address to integer or decimal number
+5.9k Golang : Get missing location after unmarshal binary and gob decode time.
+8.7k Golang : Get SPF and DMARC from email headers to fight spam
+3.5k Java : Random alphabets, alpha-numeric or numbers only string generator
+10k Golang : Convert file content to Hex
+17.2k Golang : Find smallest number in array
+9.7k Golang : Identifying Golang HTTP client request
+10.3k Golang : ISO8601 Duration Parser example
+5.5k Fix yum-complete-transaction error
+6.9k Golang : Transform lisp or spinal case to Pascal case example
+6.4k Golang : Warp text string by number of characters or runes example