nginx authelia-authrequest.conf for subnet - nginx

I'm posting this topic because I have a problem with nginx configuration on authelia with ip filtering.
Here is my current configuration.
####BABBYBUDDY####
map $remote_addr $is_allowed {
192.168.1.120 1;
default 0;
}
include /etc/nginx/conf/user-agent/user-agent-babby.domain.tld.conf;
server {
listen 80;
listen 443 ssl http2;
server_name babby.domain.tld;
if ($scheme != "https") {
rewrite ^ https://$host$uri permanent;
}
include /etc/nginx/conf/ssl/ssl.conf;
include /etc/nginx/conf/ssl/domain/cert.domain.tld.conf;
include /etc/nginx/conf/error-page/error-page.conf;
charset utf-8;
include /etc/nginx/conf/auth/authelia/authelia-location.conf;
location / {
if ($user_agent = 0) { return 403; }
if ($is_allowed = 0) {
include /etc/nginx/conf/auth/authelia/authelia-authrequest.conf;
}
proxy_pass http://babybuddy:8000;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
}
}
authelia-authrequest.conf
## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
auth_request /authelia;
## Set the $target_url variable based on the original request.
auth_request_set $target_url $scheme://$http_host$request_uri;
## Save the upstream response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
## Inject the response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://auth.domain.tld/?rd=$target_url;
I want to load the selement file based on the remote ip.
Error nginxnginx: [emerg] "auth_request" directive is not allowed here in /etc/nginx/conf/auth/authelia/authelia-authrequest.conf:2
Thank you in advance.
Transfer the config from authelia-authrequest.conf to the base file.

Related

How to pass cookie (django session id) in redirect using Nginx?

I've some problems. I have service main.example.com based on Django framework and service service.example.com based on fastAPI. In service.example.com absent User authentication. To get access, I use Django session id. In sub-service when user request page, fastAPI check Django session id in Cookies. That is, if the user is not authorized in Django, then he will not get into service.example.com. The service checks endpoint main.example.com/api/verify_session and it return client info. Also I have main.example.com/link_to_redirect to open my sub-service.
When I follow the link, in theory I pass Cookies with id session from Django to the second service and successfully enter in sub-service. On a local server all works without SSL, but with the use of configuration below the cookies are not transmitted in the redirect.
wrong cookies.
In local version without SSL service.example.com I get session_id, client_id, auth_token
Container 1 :
server {
listen 80;
server_name main.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name main.example.com;
set $dev 192.168.100.200;
proxy_cookie_flags ~ secure httponly samesite=None;
ssl_certificate /etc/letsencrypt/live/main.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/main.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://$dev:5005;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Host $http_host;
}
location /link_to_redirect {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Cookie $http_cookie;
rewrite ^ https://service.example.com/summary/ permanent;
}
}
Container 2 :
server {
listen 80;
server_name service.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name service.example.com;
ssl_certificate /etc/letsencrypt/live/service.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/service.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
proxy_cookie_flags ~ secure httponly samesite=None;
location / {
proxy_pass http://192.168.100.200:8082;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Host $http_host;
proxy_set_header Cookie $http_cookie;
}
}
I think that main problem consists in SSL directive nginx and I have no ideas how to fix it.
Thanks for all answers.

Nginx and Oauth2-proxy: After logging in with Google, redirects back to Oauth login page

I am trying to use Oauth2-proxy as a gateway to my web site with Google auth. The Oauth login page appears, and you can click "Sign In" which takes you to a Google login page, but after logging in it redirects straight back to the Oauth login page. I suspect it has something to do with cookies but I don't know where I'm going wrong.
NGINX config:
server {
listen 443;
server_name my.website.com;
ssl on;
ssl_certificate /etc/ssl/my.website.com.pem;
ssl_certificate_key /etc/ssl/my.website.com.key;
location /oauth2/ {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
location = /oauth2/auth {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --pass-access-token, this will pass the token to the backend
auth_request_set $token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Access-Token $token;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb
# limit and so the OAuth2 Proxy splits these into multiple parts.
# Nginx normally only copies the first `Set-Cookie` header from the auth_request to the respon$
# so if your cookies are larger than 4kb, you will need to extract additional cookies manually.
auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1;
# Extract the Cookie attributes from the first Set-Cookie header and append them
# to the second part ($upstream_cookie_* variables only contain the raw cookie content)
if ($auth_cookie ~* "(; .*)") {
set $auth_cookie_name_0 $auth_cookie;
set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1";
}
# Send both Set-Cookie headers now if there was a second part
if ($auth_cookie_name_upstream_1) {
add_header Set-Cookie $auth_cookie_name_0;
add_header Set-Cookie $auth_cookie_name_1;
}
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass "http://127.0.0.1:8888"; # This is where my web server is hosted
}
}
Oauth2-proxy config:
cookie_secret="" # Filled in with a base64 string
provider="google"
email_domains="*"
client_secret="" # Filled in with Google auth client secret
client_id="" # Filled in with Google auth client ID
cookie_secure="false" # No idea what to set this as, tried both false and true, same result
redirect_url="https://my.website.com/oauth2/auth/"
upstreams="http://127.0.0.1:8888/" # My website server
Oauth2-proxy startup command:
~/oauth2-proxy-v6.1.1.linux-amd64/oauth2-proxy --config=/home/username/work/src/github.com/oauth2-proxy/oauth2-proxy/contrib/local-environment/oauth2-proxy.cfg
Any ideas would be greatly appreciated!
According to the documentation
--redirect-url is the OAuth Redirect URL, should be set to supported callback endpoint , e.g. "https://internalapp.yourcompany.com/oauth2/callback".
/oauth2/callback endpoint - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url.
The actual generated url has a state parameter, that includes the original URL to return back.
As I understand, callback retrieves from the state the original (protected by the proxy) url and redirects browser to it.
The answer I accepted is correct, but I also had to make some cookie changes and figured I should just post my final, working code.
I was able to get it working with these changes:
Under location /oauth2/:
proxy_set_header X-Auth-Request-Redirect "https://my.website.com";
Under location /:
auth_request_set $auth_cookie $upstream_http_set_cookie;
In Oauth2-proxy config (additional or replacement lines):
redirect_url = "https://my.website.com/oauth2/callback"
set_xauthrequest = true
upstreams = ["file:///dev/null"]
cookie_domains = [".website.com"]
cookie_secure = false
cookie_samesite = "lax"
edit: final contents of the config files:
NGINX config:
server {
listen 443;
server_name my.website.com;
ssl on;
ssl_certificate /etc/ssl/my.website.com.pem;
ssl_certificate_key /etc/ssl/my.website.com.key;
location /oauth2/ {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect "https://my.website.com";
}
location = /oauth2/auth {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
auth_request_set $token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Access-Token $token;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1;
if ($auth_cookie ~* "(; .*)") {
set $auth_cookie_name_0 $auth_cookie;
set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1";
}
if ($auth_cookie_name_upstream_1) {
add_header Set-Cookie $auth_cookie_name_0;
add_header Set-Cookie $auth_cookie_name_1;
}
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass "http://127.0.0.1:8888"; # This is where my web server is hosted
}
}
Oauth2-proxy config:
cookie_secret="" # Filled in with a base64 string
provider="google"
email_domains="*"
client_secret="" # Filled in with Google auth client secret
client_id="" # Filled in with Google auth client ID
cookie_domains=[".website.com"]
cookie_secure="false"
cookie_samesite="lax"
redirect_url="https://my.website.com/oauth2/callback"
upstreams="http://127.0.0.1:8888/" # My website server
set_xauthrequest=true
upstreams=["file:///dev/null"]
You are going back to the oauth page because you have set (in Oauth2-proxy config)
redirect_url="https://my.website.com/oauth2/auth/"
Change it to just https://my.website.com/ for example,to land on your website home screen.

proxy_pass with nginx variable as argument

i want to use nginx set directive to use a variable as argument of proxy_pass but doing so ends up in a endless 301 Moved Permanently error in chrome when accessing https://foo.de/myleaps with the code below:
example code
user "reverse-proxy" "reverse-proxy";
error_log stderr;
daemon off;
events {}
http {
server {
listen 80;
listen [::]:80;
server_name foo.de;
location /myleaps {
rewrite ^ https://$server_name$request_uri? permanent;
}
} server {
ssl on;
listen 443 ssl;
listen [::]:443 ssl;
server_name foo.de;
ssl_certificate /var/lib/nixcloud/TLS/foo.de/selfsigned/fullchain.pem;
ssl_certificate_key /var/lib/nixcloud/TLS/foo.de/selfsigned/key.pem;
location /myleaps {
set $tttt http://127.0.0.1:3031/myleaps;
# https default flags
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass $tttt;
}
location /myleaps/leaps/ws {
# https websocket default flags
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 36000s;
# required because of CORS
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3031/myleaps/leaps/ws;
}
}
}
using hardcoded values (no set)
when using this:
proxy_pass http://127.0.0.1:3031/myleaps;
instead of:
proxy_pass $tttt;
it works for my example.
so the question is: why does proxy_pass work with an hard coded string but not with using a variable?
motivation
in the reverse-proxy here https://github.com/nixcloud/nixcloud-webservices/blob/be57d526547c66db05595002682525ca62c8f068/modules/services/reverse-proxy/default.nix#L144 the code which generates the proxy_pass is basically hardcoded and if a user wishes to override this it is going to be really complicated. so the idea is to generate 3 variables: ip, port and path and put it into the location scope and let the user later use these. this way i could get rid of the hardcoded proxy_pass directive and the user would be much more flexible in modifying/generating the location record.
so the code could be like this:
set $targetIP = ${location.ip};
set $targetPort = ${toString location.port}
set $targetPath = ${removeSuffix "/" (toString (builtins.toPath (location.path)))};
and the 3 lines above would always be generated into that location record, no matter what. but the code below is dynamically generated and a default implementation could be this:
proxy_pass http://$targetIP:$targetPort$targetPath;
but the user could simply override it by:
nixcloud.reverse-proxy = {
enable = true;
extendEtcHosts = true;
extraMappings = [
{
domain = "example.com";
path = "/";
https = {
mode = "on";
basicAuth."joachim" = "foo";
record = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://$targetIP:$targetPort$targetPath
'';
};
}
];
};
it is working using $request_uri instead of hardcoding the proxy_pass path using $targetPath:
set $targetIP 127.0.0.1;
set $targetPort 3031;
proxy_pass http://$targetIP:$targetPort$request_uri;
this code will soon be in nixcloud-webservices!
thanks to irc.freenode.net#nginx#benbrown (Ben Brown) for this solution!

NGINX frontending Kibana not working with "_plugin/kibana/" URI

I'm running the AWS Managed ElasticSearch to collect some logs and have created some Kibana dashboards to visualise the data, all that works fine.
Unfortunately the Kibana plugin included on with the AWS cluster is pretty much open to the world, so I have setup an NGINX reverse proxy to provide authenticated access. This is also working fine if I simply hit the domain URL and specify the full URI to the Kibana plugin. For example:
http://nginx.domain.com/_plugin/kibana/app/kibana works just fine, here in the nginx configuration I am using to achieve that:
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header User-Agent $http_user_agent;
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Auth Required";
proxy_pass https://search-mystuff.ap-southeast-2.es.amazonaws.com/;
proxy_redirect https://search-mystuff.ap-southeast-2.es.amazonaws.com/ /;
proxy_set_header Authorization "";
proxy_hide_header Authorization;
}
}
}
Rather than providing the full URL, I would like to simply hit the base domain name of the NGINX server, which would then redirect me to the full Kibana URI. So what I would LIKE to do is this:
http://nginx.domain.com
After entering the above URL, I would like to be redirected to the full Kibana URI, so I would end up with a URL like this
http://nginx.domain.com/_plugin/kibana/app/kibana
Here is the nginx configuration I have tried (in various different permutations) that does not work:
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header User-Agent $http_user_agent;
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Auth Required";
proxy_pass https://search-mystuff.ap-southeast-2.es.amazonaws.com/_plugin/kibana/app/kibana;
proxy_redirect https://search-mystuff.ap-southeast-2.es.amazonaws.com/_plugin/kibana/app/kibana /;
proxy_set_header Authorization "";
proxy_hide_header Authorization;
}
}
}
With the configuration above, when I browse to http://nginx.mydomain.com the URL is redirected to:
http://nginx.myaws.com.au/_plugin/kibana/app/kibana
This looks like it SHOULD work, however I receive an error in the browser window:
{"statusCode":404,"error":"Not Found"}
I have about 4 hours experience with nginx, so hopefully I'm missing something simple. Any help would be very much appreciated.
Thank you!
Got it, finally!
worker_processes auto;
events {
worker_connections 1024;
}
http {
server {
listen 80 default_server;
server_name localhost;
location / {
proxy_set_header Host https://<endpoint address>.es.amazonaws.com;
proxy_set_header X-Real-IP <nginx ip address>;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
proxy_set_header Authorization "";
proxy_pass https://<endpoint address>.es.amazonaws.com/_plugin/kibana/;
proxy_redirect https://<endpoint address>.es.amazonaws.com/_plugin/kibana/ http://<nginx url>/kibana/;
}
location ~ (/app/kibana|/app/timelion|/bundles|/es_admin|/plugins|/api|/ui|/elasticsearch) {
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Auth Required";
proxy_pass https://<endpoint address>.es.amazonaws.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Authorization "";
proxy_hide_header Authorization;
}
}
}

ERR_TOO_MANY_REDIRECTS while setting up Ghost + Nginx with both HTTP and HTTPS

I'm deploying Ghost (0.7.6) in a VPS using Nginx (1.8.1). To make the dashboard and sign-in page secure, I force any request to use HTTPS when accessing such pages (such as /ghost page). But, for any request to any other page (such as accessing the Ghost blog itself) I want to force it to use HTTP. Ghost is up listening on 127.0.0.1:2368.
Strangely, the result is not as what I expected: Every time I access my blog (let's say the url is a.b), it says that my site has ERR_TOO_MANY_REDIRECTS and it redirects between http://a.b and https://a.b (or between http://a.b/signin and https://a.b/signin). BUT, when I access the admin dashboard (https://a.b/ghost or http://a.b/ghost), it acts as expected (no error, correctly redirects to use HTTPS).
Any help?
My Nginx configuration:
# Configuration for http://a.b
server {
listen 80;
server_name a.b;
location ^~ /ghost { # /ghost should be accessed securely
return 301 https://$host$request_uri;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2368;
}
}
# Configuration for http://a.b
server {
listen 443 ssl;
server_name a.b;
ssl_certificate ...;
ssl_certificate_key ...;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers '...';
location ^~ /ghost { # /ghost should be accessed securely
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2368;
}
location / { # Force to use HTTP
return 301 http://$host$request_uri;
}
}
Any kind of help would be appreciated :')
https://github.com/TryGhost/Ghost/issues/2796
location ^~ /ghost { # /ghost should be accessed securely
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2368;
}

Resources