38 lines
1.4 KiB
Go
38 lines
1.4 KiB
Go
package api
|
||
|
||
import (
|
||
"net/http"
|
||
"testing"
|
||
)
|
||
|
||
// clientIP не должен доверять первому элементу X-Forwarded-For (его задаёт клиент),
|
||
// иначе rate-limit обходится подменой заголовка.
|
||
func TestClientIPTrust(t *testing.T) {
|
||
cases := []struct {
|
||
name string
|
||
xRealIP string
|
||
xff string
|
||
remoteAddr string
|
||
want string
|
||
}{
|
||
{"x-real-ip от прокси", "203.0.113.5", "6.6.6.6, 203.0.113.5", "172.17.0.1:5000", "203.0.113.5"},
|
||
{"без real-ip: берём последний xff", "", "6.6.6.6, 203.0.113.7", "172.17.0.1:5000", "203.0.113.7"},
|
||
{"подделка одним xff не проходит", "", "6.6.6.6", "172.17.0.1:5000", "6.6.6.6"}, // один прокси добавил бы свой; тут проверяем, что берём последний
|
||
{"без заголовков: RemoteAddr", "", "", "198.51.100.9:44321", "198.51.100.9"},
|
||
{"мусор в real-ip игнорируется", "not-an-ip", "", "198.51.100.9:44321", "198.51.100.9"},
|
||
}
|
||
for _, c := range cases {
|
||
r, _ := http.NewRequest("GET", "/", nil)
|
||
r.RemoteAddr = c.remoteAddr
|
||
if c.xRealIP != "" {
|
||
r.Header.Set("X-Real-IP", c.xRealIP)
|
||
}
|
||
if c.xff != "" {
|
||
r.Header.Set("X-Forwarded-For", c.xff)
|
||
}
|
||
if got := clientIP(r); got != c.want {
|
||
t.Errorf("%s: clientIP=%q, ожидали %q", c.name, got, c.want)
|
||
}
|
||
}
|
||
}
|