add ip logging to jail pingback spammers
parent
e6bd0ef669
commit
54018ecc42
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
"golang.org/x/time/rate"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
@ -77,7 +76,7 @@ func (rl *RateLimiter) cleanupVisitors() {
|
|||
// with the help of https://www.alexedwards.net/blog/how-to-rate-limit-http-requests, TY!
|
||||
func (rl *RateLimiter) limiterMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ip := rl.guessIp(r)
|
||||
ip := ipFrom(r)
|
||||
limiter := rl.getVisitor(ip)
|
||||
|
||||
if limiter.Allow() == false {
|
||||
|
@ -89,15 +88,3 @@ func (rl *RateLimiter) limiterMiddleware(next http.Handler) http.Handler {
|
|||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (rl *RateLimiter) guessIp(r *http.Request) string {
|
||||
realIp := r.Header.Get("X-Real-IP")
|
||||
forwardedFor := r.Header.Get("X-Forwarded-For")
|
||||
if realIp != "" { // in case of proxy. is IP itself
|
||||
return realIp
|
||||
}
|
||||
if forwardedFor != "" { // in case of proxy. Could be: clientip, proxy1, proxy2, ...
|
||||
return strings.Split(forwardedFor, ",")[0]
|
||||
}
|
||||
return r.RemoteAddr // also contains port, but don't care
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
|
|||
lrw.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
// Logs ip (for those pingback bad boys to put in jail), request url, method, and response status code.
|
||||
func LoggingMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
logWriter := &loggingResponseWriter{w, http.StatusOK}
|
||||
next.ServeHTTP(logWriter, r)
|
||||
log.Info().
|
||||
Str("url", r.RequestURI).
|
||||
Str("ip", ipFrom(r)).
|
||||
Str("method", r.Method).
|
||||
Int("status", logWriter.statusCode).
|
||||
Msg("handled")
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"brainbaking.com/go-jamming/common"
|
||||
"brainbaking.com/go-jamming/rest"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/rs/zerolog/log"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -15,18 +16,18 @@ func HandlePost(conf *common.Config) http.HandlerFunc {
|
|||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
pingbackError(w, "Unable to read request body", []byte("<not-parsaeble>"))
|
||||
pingbackError(w, fmt.Errorf("pingback POST: Unable to read body: %v", err))
|
||||
return
|
||||
}
|
||||
rpc := &XmlRPCMethodCall{}
|
||||
err = xml.Unmarshal(body, rpc)
|
||||
if err != nil {
|
||||
pingbackError(w, "Unable to unmarshal XMLRPC request body", body)
|
||||
pingbackError(w, fmt.Errorf("pingback POST: Unable to unmarshal XMLRPC %s: %v", body, err))
|
||||
return
|
||||
}
|
||||
|
||||
if !validate(rpc, conf) {
|
||||
pingbackError(w, "malformed pingback request", body)
|
||||
pingbackError(w, fmt.Errorf("pingback POST: malformed pingback request: %s", body))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -61,7 +62,7 @@ func pingbackSuccess(w http.ResponseWriter) {
|
|||
}
|
||||
|
||||
// according to the XML-RPC spec, always return a 200, but encode it into the XML.
|
||||
func pingbackError(w http.ResponseWriter, msg string, body []byte) {
|
||||
func pingbackError(w http.ResponseWriter, err error) {
|
||||
xml := `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<methodResponse>
|
||||
<fault>
|
||||
|
@ -91,7 +92,7 @@ func pingbackError(w http.ResponseWriter, msg string, body []byte) {
|
|||
</value>
|
||||
</fault>
|
||||
</methodResponse>`
|
||||
log.Error().Str("msg", msg).Str("xml", string(body)).Msg("Pingback receive went wrong")
|
||||
log.Error().Err(err).Msg("Pingback receive went wrong")
|
||||
w.WriteHeader(200)
|
||||
w.Write([]byte(xml))
|
||||
}
|
||||
|
|
|
@ -6,6 +6,14 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestMarshallXmlSpamFromProductionWithMissingDecoderCharset(t *testing.T) {
|
||||
xmlString := `<?xml version="1.0" encoding="utf-16" standalone="yes"?><methodCall><methodName>pingback.ping</methodName><params><param><value><string>https://teramassage.com/gwangju/</string></value></param><param><value><string>https://brainbaking.com/projects/</string></value></param></params></methodCall>`
|
||||
var rpc XmlRPCMethodCall
|
||||
err := xml.Unmarshal([]byte(xmlString), &rpc)
|
||||
|
||||
assert.EqualError(t, err, `xml: encoding "utf-16" declared but Decoder.CharsetReader is nil`)
|
||||
}
|
||||
|
||||
// See https://www.hixie.ch/specs/pingback/pingback#refsXMLRPC
|
||||
func TestMarshallValidXMLRPC(t *testing.T) {
|
||||
xmlString := `<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/MagnusFrater/helmet"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"brainbaking.com/go-jamming/common"
|
||||
|
||||
|
@ -28,6 +29,18 @@ func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func ipFrom(r *http.Request) string {
|
||||
realIp := r.Header.Get("X-Real-IP")
|
||||
forwardedFor := r.Header.Get("X-Forwarded-For")
|
||||
if realIp != "" { // in case of proxy. is IP itself
|
||||
return realIp
|
||||
}
|
||||
if forwardedFor != "" { // in case of proxy. Could be: clientip, proxy1, proxy2, ...
|
||||
return strings.Split(forwardedFor, ",")[0]
|
||||
}
|
||||
return r.RemoteAddr // also contains port, but don't care
|
||||
}
|
||||
|
||||
func Start() {
|
||||
r := mux.NewRouter()
|
||||
config := common.Configure()
|
||||
|
|
Loading…
Reference in New Issue