diff --git a/anubis.go b/anubis.go index 67fa006..225a47e 100644 --- a/anubis.go +++ b/anubis.go @@ -23,6 +23,9 @@ const CookieDefaultExpirationTime = 7 * 24 * time.Hour // BasePrefix is a global prefix for all Anubis endpoints. Can be emptied to remove the prefix entirely. var BasePrefix = "" +// PublicUrl is the externally accessible URL for this Anubis instance. +var PublicUrl = "" + // StaticPath is the location where all static Anubis assets are located. const StaticPath = "/.within.website/x/cmd/anubis/" diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index bd5e1ae..1ba56bb 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add a default block rule for Huawei Cloud. - Add a default block rule for Alibaba Cloud. - Add X-Request-URI support so that Subrequest Authentication has path support. +- Added support to use Traefik forwardAuth middleware. ### Security-relevant changes @@ -286,7 +287,6 @@ And some cleanups/refactors were added: - Bump AI-robots.txt to version 1.37 - Make progress bar styling more compatible (UXP, etc) - Add `--strip-base-prefix` flag/envvar to strip the base prefix from request paths when forwarding to target servers -- Added support to use Traefik forwardAuth middleware - Fix an off-by-one in the default threshold config - Add functionality for HS512 JWT algorithm - Add support for dynamic cookie domains with the `--cookie-dynamic-domain`/`COOKIE_DYNAMIC_DOMAIN` flag/envvar diff --git a/lib/anubis.go b/lib/anubis.go index 3fd9e68..0e73b1e 100644 --- a/lib/anubis.go +++ b/lib/anubis.go @@ -435,6 +435,7 @@ func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) { return } if (len(urlParsed.Host) > 0 && len(s.opts.RedirectDomains) != 0 && !slices.Contains(s.opts.RedirectDomains, urlParsed.Host)) || urlParsed.Host != r.URL.Host { + lg.Debug("domain not allowed", "domain", urlParsed.Host) s.respondWithError(w, r, localizer.T("redirect_domain_not_allowed")) return } diff --git a/lib/config.go b/lib/config.go index 101d0ab..58c4a4a 100644 --- a/lib/config.go +++ b/lib/config.go @@ -106,6 +106,7 @@ func New(opts Options) (*Server, error) { } anubis.BasePrefix = opts.BasePrefix + anubis.PublicUrl = opts.PublicUrl result := &Server{ next: opts.Next, diff --git a/lib/http.go b/lib/http.go index 5418032..b1a449d 100644 --- a/lib/http.go +++ b/lib/http.go @@ -212,12 +212,16 @@ func (s *Server) constructRedirectURL(r *http.Request) (string, error) { host := r.Header.Get("X-Forwarded-Host") uri := r.Header.Get("X-Forwarded-Uri") + localizer := localization.GetLocalizer(r) + if proto == "" || host == "" || uri == "" { - return "", errors.New("missing required X-Forwarded-* headers") + return "", errors.New(localizer.T("missing_required_forwarded_headers")) } // Check if host is allowed in RedirectDomains if len(s.opts.RedirectDomains) > 0 && !slices.Contains(s.opts.RedirectDomains, host) { - return "", errors.New("redirect domain not allowed") + lg := internal.GetRequestLogger(s.logger, r) + lg.Debug("domain not allowed", "domain", host) + return "", errors.New(localizer.T("redirect_domain_not_allowed")) } redir := proto + "://" + host + uri @@ -290,6 +294,8 @@ func (s *Server) ServeHTTPNext(w http.ResponseWriter, r *http.Request) { hostMismatch := r.URL.Host != "" && urlParsed.Host != r.URL.Host if hostNotAllowed || hostMismatch { + lg := internal.GetRequestLogger(s.logger, r) + lg.Debug("domain not allowed", "domain", urlParsed.Host) s.respondWithStatus(w, r, localizer.T("redirect_domain_not_allowed"), http.StatusBadRequest) return } diff --git a/lib/localization/locales/cs.json b/lib/localization/locales/cs.json index 8d21d3e..db4eded 100644 --- a/lib/localization/locales/cs.json +++ b/lib/localization/locales/cs.json @@ -61,5 +61,6 @@ "js_iterations": "iterací", "js_finished_reading": "Čtení dokončeno, pokračovat →", "js_calculation_error": "Chyba výpočtu!", - "js_calculation_error_msg": "Nepodařilo se vypočítat výzvu:" + "js_calculation_error_msg": "Nepodařilo se vypočítat výzvu:", + "missing_required_forwarded_headers": "Chybějící požadované hlavičky X-Forwarded-*" } \ No newline at end of file diff --git a/lib/localization/locales/de.json b/lib/localization/locales/de.json index 670a5f8..cf47ae3 100644 --- a/lib/localization/locales/de.json +++ b/lib/localization/locales/de.json @@ -61,5 +61,6 @@ "js_finished_reading": "Fertig gelesen, weiter zur Seite →", "js_calculation_error": "Berechnung fehlgeschlagen!", "js_calculation_error_msg": "Fehler bei der Berechnung der Prüfung:", + "missing_required_forwarded_headers": "Fehlende erforderliche X-Forwarded-* Header", "simplified_explanation": "Dies ist eine Maßnahme gegen Bots und bösartige Anfragen, ähnlich einem CAPTCHA. Anstatt jedoch selbst arbeiten zu müssen, erhält Ihr Browser eine Berechnungsaufgabe, die er lösen muss, um sicherzustellen, dass es sich um einen gültigen Client handelt. Dieses Konzept wird als Proof of Work bezeichnet. Die Aufgabe wird in wenigen Sekunden berechnet und Sie erhalten Zugriff auf die Website. Vielen Dank für Ihr Verständnis und Ihre Geduld." } \ No newline at end of file diff --git a/lib/localization/locales/en.json b/lib/localization/locales/en.json index f3c8ef5..0280b97 100644 --- a/lib/localization/locales/en.json +++ b/lib/localization/locales/en.json @@ -36,6 +36,7 @@ "invalid_redirect": "Invalid redirect", "redirect_not_parseable": "Redirect URL not parseable", "redirect_domain_not_allowed": "Redirect domain not allowed", + "missing_required_forwarded_headers": "Missing required X-Forwarded-* headers", "failed_to_sign_jwt": "failed to sign JWT", "invalid_invocation": "Invalid invocation of MakeChallenge", "client_error_browser": "Client Error: Please ensure your browser is up to date and try again later.", diff --git a/lib/localization/locales/es.json b/lib/localization/locales/es.json index 6fd4bd4..8beb3bf 100644 --- a/lib/localization/locales/es.json +++ b/lib/localization/locales/es.json @@ -61,5 +61,6 @@ "js_finished_reading": "He terminado de leer, continuar →", "js_calculation_error": "¡Error de cálculo!", "js_calculation_error_msg": "Falló al calcular el desafío:", + "missing_required_forwarded_headers": "Faltan los encabezados X-Forwarded-* requeridos", "simplified_explanation": "Esta es una medida contra bots y solicitudes maliciosas similar a un CAPTCHA. Sin embargo, en lugar de tener que hacer el trabajo usted mismo, a su navegador se le asigna una tarea de cálculo que debe resolver para garantizar que es un cliente válido. Este concepto se llama Prueba de trabajo. La tarea se calcula en unos segundos y se le concede acceso al sitio web. Gracias por su comprensión y paciencia." } \ No newline at end of file diff --git a/lib/localization/locales/et.json b/lib/localization/locales/et.json index cf28327..09125b9 100644 --- a/lib/localization/locales/et.json +++ b/lib/localization/locales/et.json @@ -61,5 +61,6 @@ "js_finished_reading": "Lugesin ära, edasi →", "js_calculation_error": "Arvutamise viga!", "js_calculation_error_msg": "Ei suutnud kontrolli arvutada:", + "missing_required_forwarded_headers": "Puuduvad nõutud X-Forwarded-* päised", "simplified_explanation": "See on meede robotite ja pahatahtlike päringute vastu, mis sarnaneb CAPTCHA-le. Kuid selle asemel, et peaksite ise tööd tegema, antakse teie brauserile arvutusülesanne, mille see peab lahendama, et tagada selle kehtivus kliendina. Seda kontseptsiooni nimetatakse Töötõendiks. Ülesanne arvutatakse mõne sekundiga ja teile antakse juurdepääs veebisaidile. Täname teid mõistva suhtumise ja kannatlikkuse eest." } \ No newline at end of file diff --git a/lib/localization/locales/fi.json b/lib/localization/locales/fi.json index 25d3c09..bd06d3a 100644 --- a/lib/localization/locales/fi.json +++ b/lib/localization/locales/fi.json @@ -61,5 +61,6 @@ "js_finished_reading": "Luettu, jatka →", "js_calculation_error": "Laskentavirhe!", "js_calculation_error_msg": "Haasteen laskenta ei onnistunut:", + "missing_required_forwarded_headers": "Puuttuvat vaaditut X-Forwarded-* otsikot", "simplified_explanation": "Tämä on toimenpide botteja ja haitallisia pyyntöjä vastaan, joka on samanlainen kuin CAPTCHA. Sen sijaan, että joutuisit tekemään työtä itse, selaimesi saa laskentatehtävän, joka sen on ratkaistava varmistaakseen, että se on kelvollinen asiakas. Tätä käsitettä kutsutaan nimellä Työtodistus. Tehtävä lasketaan muutamassa sekunnissa ja saat pääsyn verkkosivustolle. Kiitos ymmärryksestäsi ja kärsivällisyydestäsi." } \ No newline at end of file diff --git a/lib/localization/locales/fil.json b/lib/localization/locales/fil.json index ad24dc7..ab89d03 100644 --- a/lib/localization/locales/fil.json +++ b/lib/localization/locales/fil.json @@ -61,5 +61,6 @@ "js_finished_reading": "Tapos na akong magbasa, magpatuloy →", "js_calculation_error": "Error sa pagkalkula!", "js_calculation_error_msg": "Nabigong ikalkula ang hamon:", + "missing_required_forwarded_headers": "Nawawala ang kinakailangang X-Forwarded-* na mga header", "simplified_explanation": "Ito ay isang panukala laban sa mga bot at malisyosong mga kahilingan na katulad ng isang CAPTCHA. Gayunpaman, sa halip na ikaw mismo ang gumawa ng trabaho, binibigyan ang iyong browser ng isang gawain sa pagkalkula na kailangan nitong lutasin upang matiyak na ito ay isang wastong kliyente. Ang konseptong ito ay tinatawag na Proof of Work. Ang gawain ay kinakalkula sa loob ng ilang segundo at binibigyan ka ng access sa website. Salamat sa iyong pag-unawa at pasensya." } diff --git a/lib/localization/locales/fr.json b/lib/localization/locales/fr.json index b8ac335..b696e04 100644 --- a/lib/localization/locales/fr.json +++ b/lib/localization/locales/fr.json @@ -61,5 +61,6 @@ "js_finished_reading": "J'ai fini de lire, continuer →", "js_calculation_error": "Erreur de calcul !", "js_calculation_error_msg": "Échec du calcul du défi :", + "missing_required_forwarded_headers": "En-têtes X-Forwarded-* requis manquants", "simplified_explanation": "Il s'agit d'une mesure contre les robots et les requêtes malveillantes similaire à un CAPTCHA. Cependant, au lieu d'avoir à faire le travail vous-même, votre navigateur se voit confier une tâche de calcul qu'il doit résoudre pour s'assurer qu'il est un client valide. Ce concept s'appelle Preuve de travail. La tâche est calculée en quelques secondes et vous avez accès au site Web. Merci de votre compréhension et de votre patience." } \ No newline at end of file diff --git a/lib/localization/locales/is.json b/lib/localization/locales/is.json index 70b1bef..b4f624b 100644 --- a/lib/localization/locales/is.json +++ b/lib/localization/locales/is.json @@ -61,5 +61,6 @@ "js_finished_reading": "Ég hef lokið lestrinum, höldum áfram →", "js_calculation_error": "Reiknivilla!", "js_calculation_error_msg": "Mistókst að reikna áskorun:", + "missing_required_forwarded_headers": "Vantar nauðsynleg X-Forwarded-* hausar", "simplified_explanation": "Þetta er ráðstöfun gegn vélmennum og illgjarnum beiðnum svipað og CAPTCHA. Hins vegar, í stað þess að þurfa að vinna sjálfur, fær vafrinn þinn útreikningsverkefni sem hann þarf að leysa til að tryggja að hann sé gildur biðlari. Þetta hugtak er kallað Sönnun-á-vinnu. Verkefnið er reiknað á nokkrum sekúndum og þú færð aðgang að vefsíðunni. Takk fyrir skilninginn og þolinmæðina." } diff --git a/lib/localization/locales/it.json b/lib/localization/locales/it.json index 97f32b5..e2ecc11 100644 --- a/lib/localization/locales/it.json +++ b/lib/localization/locales/it.json @@ -61,5 +61,6 @@ "js_finished_reading": "Ho finito di leggere, continua →", "js_calculation_error": "Errore nel calcolo!", "js_calculation_error_msg": "Impossibile superare il test:", + "missing_required_forwarded_headers": "Mancano gli header X-Forwarded-* richiesti", "simplified_explanation": "Questa è una misura contro bot e richieste dannose simile a un CAPTCHA. Tuttavia, invece di dover lavorare tu stesso, al tuo browser viene assegnato un compito di calcolo che deve risolvere per garantire che sia un client valido. Questo concetto è chiamato Proof of Work. Il compito viene calcolato in pochi secondi e ti viene concesso l'accesso al sito web. Grazie per la tua comprensione e pazienza." } \ No newline at end of file diff --git a/lib/localization/locales/ja.json b/lib/localization/locales/ja.json index 751d9c2..3042173 100644 --- a/lib/localization/locales/ja.json +++ b/lib/localization/locales/ja.json @@ -61,5 +61,6 @@ "js_finished_reading": "読み終わりました。続行 →", "js_calculation_error": "計算エラー!", "js_calculation_error_msg": "チャレンジの計算に失敗しました:", + "missing_required_forwarded_headers": "必要な X-Forwarded-* ヘッダーがありません", "simplified_explanation": "これは、CAPTCHAと同様の、ボットや悪意のあるリクエストに対する対策です。ただし、自分で作業する代わりに、ブラウザに計算タスクが与えられ、それを解決して有効なクライアントであることを確認する必要があります。この概念はProof of Workと呼ばれます。タスクは数秒で計算され、ウェブサイトへのアクセスが許可されます。ご理解とご協力をお願いいたします。" } \ No newline at end of file diff --git a/lib/localization/locales/nb.json b/lib/localization/locales/nb.json index 1090046..0b8b6fc 100644 --- a/lib/localization/locales/nb.json +++ b/lib/localization/locales/nb.json @@ -61,5 +61,6 @@ "js_finished_reading": "Jeg har sluttet å lese, fortsett →", "js_calculation_error": "Beregningsfeil!", "js_calculation_error_msg": "Mislyktes i å beregne utfordring:", + "missing_required_forwarded_headers": "Mangler nødvendige X-Forwarded-* header", "simplified_explanation": "Dette er et tiltak mot roboter og ondsinnede forespørsler som ligner på en CAPTCHA. Men i stedet for å måtte gjøre arbeidet selv, får nettleseren din en beregningsoppgave som den må løse for å sikre at den er en gyldig klient. Dette konseptet kalles Proof of Work. Oppgaven beregnes på noen få sekunder, og du får tilgang til nettstedet. Takk for din forståelse og tålmodighet." } \ No newline at end of file diff --git a/lib/localization/locales/nl.json b/lib/localization/locales/nl.json index 936d4b2..990a012 100644 --- a/lib/localization/locales/nl.json +++ b/lib/localization/locales/nl.json @@ -61,5 +61,6 @@ "js_finished_reading": "Ik ben klaar met lezen, ga verder →", "js_calculation_error": "Rekenfout!", "js_calculation_error_msg": "Uitdaging niet berekend:", + "missing_required_forwarded_headers": "Ontbrekende vereiste X-Forwarded-* headers", "simplified_explanation": "Dit is een maatregel tegen bots en kwaadwillende verzoeken, vergelijkbaar met een CAPTCHA. In plaats van dat u zelf werk moet verrichten, krijgt uw browser een rekentaak die hij moet oplossen om ervoor te zorgen dat het een geldige client is. Dit concept wordt Proof of Work genoemd. De taak wordt in een paar seconden berekend en u krijgt toegang tot de website. Bedankt voor uw begrip en geduld." } diff --git a/lib/localization/locales/nn.json b/lib/localization/locales/nn.json index a44040f..d49396a 100644 --- a/lib/localization/locales/nn.json +++ b/lib/localization/locales/nn.json @@ -61,5 +61,6 @@ "js_finished_reading": "Eg har slutta å lesa, hald fram →", "js_calculation_error": "Rekningsfeil!", "js_calculation_error_msg": "Mislukkast i å rekne utfordring:", + "missing_required_forwarded_headers": "Manglende nødvendige X-Forwarded-* headers", "simplified_explanation": "Dette er eit tiltak mot robotar og vondsinna førespurnader som liknar på ein CAPTCHA. Men i staden for å måtte gjere arbeidet sjølv, får nettlesaren din ei utrekningsoppgåve som han må løyse for å sikre at han er ein gyldig klient. Dette konseptet blir kalla Arbeidsbevis. Oppgåva blir rekna ut på nokre få sekund, og du får tilgang til nettstaden. Takk for di forståing og tålmod." } \ No newline at end of file diff --git a/lib/localization/locales/pt-BR.json b/lib/localization/locales/pt-BR.json index b1a5a37..6176968 100644 --- a/lib/localization/locales/pt-BR.json +++ b/lib/localization/locales/pt-BR.json @@ -61,5 +61,6 @@ "js_finished_reading": "Terminei de ler, continue →", "js_calculation_error": "Erro de cálculo!", "js_calculation_error_msg": "Falha ao calcular a validação:", + "missing_required_forwarded_headers": "Faltam os cabeçalhos X-Forwarded-* obrigatórios", "simplified_explanation": "Esta é uma medida contra bots e solicitações maliciosas, semelhante a um CAPTCHA. No entanto, em vez de você mesmo ter que fazer o trabalho, seu navegador recebe uma tarefa de cálculo que ele deve resolver para garantir que seja um cliente válido. Esse conceito é chamado de Prova de Trabalho. A tarefa é calculada em poucos segundos e você tem acesso ao site. Obrigado pela sua compreensão e paciência." } diff --git a/lib/localization/locales/ru.json b/lib/localization/locales/ru.json index aee253f..632efd3 100644 --- a/lib/localization/locales/ru.json +++ b/lib/localization/locales/ru.json @@ -61,5 +61,6 @@ "js_finished_reading": "Я дочитал, продолжить →", "js_calculation_error": "Ошибка расчёта!", "js_calculation_error_msg": "Не удалось рассчитать задачу:", + "missing_required_forwarded_headers": "Отсутствуют требуемые заголовки X-Forwarded-*", "simplified_explanation": "Это мера против ботов и вредоносных запросов, аналогичная CAPTCHA. Однако вместо того, чтобы вам приходилось работать самостоятельно, вашему браузеру дается задача вычисления, которую он должен решить, чтобы убедиться, что он является действительным клиентом. Эта концепция называется Доказательство выполнения работы. Задача рассчитывается за несколько секунд, и вам предоставляется доступ к веб-сайту. Спасибо за понимание и терпение." } \ No newline at end of file diff --git a/lib/localization/locales/sv.json b/lib/localization/locales/sv.json index 7de48ca..dbb18cc 100644 --- a/lib/localization/locales/sv.json +++ b/lib/localization/locales/sv.json @@ -61,5 +61,6 @@ "js_finished_reading": "Jag har läst klart, fortsätt →", "js_calculation_error": "Beräkningsfel!", "js_calculation_error_msg": "Misslyckades att kalkylera utmaning:", + "missing_required_forwarded_headers": "Saknar nödvändiga X-Forwarded-* headers", "simplified_explanation": "Detta är en åtgärd mot botar och skadliga förfrågningar som liknar en CAPTCHA. Men i stället för att du själv måste göra jobbet får din webbläsare en beräkningsuppgift som den måste lösa för att säkerställa att den är en giltig klient. Detta koncept kallas Arbetsbevis. Uppgiften beräknas på några sekunder och du beviljas tillgång till webbplatsen. Tack för din förståelse och ditt tålamod." } \ No newline at end of file diff --git a/lib/localization/locales/tr.json b/lib/localization/locales/tr.json index 0174b15..79773b5 100644 --- a/lib/localization/locales/tr.json +++ b/lib/localization/locales/tr.json @@ -61,5 +61,6 @@ "js_finished_reading": "Okumayı bitirdim, devam et →", "js_calculation_error": "Hesaplama hatası!", "js_calculation_error_msg": "Zorluk hesaplaması başarısız oldu:", + "missing_required_forwarded_headers": "Gerekli X-Forwarded-* başlıkları eksik", "simplified_explanation": "Bu, botlara ve kötü niyetli isteklere karşı CAPTCHA'ya benzer bir önlemdir. Ancak, kendiniz çalışmak yerine, tarayıcınıza geçerli bir istemci olduğundan emin olmak için çözmesi gereken bir hesaplama görevi verilir. Bu kavrama İş Kanıtı denir. Görev birkaç saniye içinde hesaplanır ve web sitesine erişim hakkı kazanırsınız. Anlayışınız ve sabrınız için teşekkür ederiz." } diff --git a/lib/localization/locales/zh-CN.json b/lib/localization/locales/zh-CN.json index 6336456..1952960 100644 --- a/lib/localization/locales/zh-CN.json +++ b/lib/localization/locales/zh-CN.json @@ -61,5 +61,6 @@ "js_finished_reading": "我读完了,继续 →", "js_calculation_error": "计算错误!", "js_calculation_error_msg": "计算挑战失败:", + "missing_required_forwarded_headers": "缺少必要的 X-Forwarded-* 头", "simplified_explanation": "这是一种类似于验证码的措施,用于防止机器人和恶意请求。但是,您无需自己动手,您的浏览器会收到一个计算任务,必须解决该任务以确保它是有效的客户端。这个概念称为工作量证明。该任务在几秒钟内计算完毕,您将被授予访问网站的权限。感谢您的理解和耐心。" } diff --git a/lib/localization/locales/zh-TW.json b/lib/localization/locales/zh-TW.json index 1e6584e..4e7da25 100644 --- a/lib/localization/locales/zh-TW.json +++ b/lib/localization/locales/zh-TW.json @@ -61,5 +61,6 @@ "js_finished_reading": "我讀完了,繼續 →", "js_calculation_error": "計算錯誤!", "js_calculation_error_msg": "計算挑戰失敗:", + "missing_required_forwarded_headers": "缺少必要的 X-Forwarded-* 標頭", "simplified_explanation": "這是一種類似於驗證碼的措施,用於防止機器人和惡意請求。但是,您無需自己動手,您的瀏覽器會收到一個計算任務,必須解決該任務以確保它是有效的客戶端。這個概念稱為工作量證明。該任務在幾秒鐘內計算完畢,您將被授予訪問網站的權限。感謝您的理解和耐心。" } \ No newline at end of file diff --git a/web/index.templ b/web/index.templ index 65d704c..54b368c 100644 --- a/web/index.templ +++ b/web/index.templ @@ -60,6 +60,7 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal @templ.JSONScript("anubis_version", anubis.Version) @templ.JSONScript("anubis_challenge", challenge) @templ.JSONScript("anubis_base_prefix", anubis.BasePrefix) + @templ.JSONScript("anubis_public_url", anubis.PublicUrl)