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) } } }