Captive portal #11

Merged
ynerant merged 20 commits from accueil into master 2021-02-05 20:39:51 +01:00
16 changed files with 578 additions and 0 deletions
Showing only changes of commit 7e4a2d20c0 - Show all commits

24
group_vars/nginx.yml Normal file
View file

@ -0,0 +1,24 @@
---
glob_nginx:
contact: tech.aurore@lists.crans.org
who: "L'équipe technique d'Aurore"
service_name: service
ssl:
cert: /etc/letsencrypt/live/auro.re/fullchain.pem
cert_key: /etc/letsencrypt/live/auro.re/privkey.pem
trusted_cert: /etc/letsencrypt/live/auro.re/chain.pem
servers:
- ssl: false
server_name:
- "default"
- "_"
root: "/var/www/html"
locations:
- filter: "/"
params: []
upstreams: []
auth_passwd: []
default_server:
default_ssl_server:
deploy_robots_file: false

View file

@ -0,0 +1,5 @@
---
- name: Reload nginx
systemd:
name: nginx
state: reloaded

121
roles/nginx/tasks/main.yml Normal file
View file

@ -0,0 +1,121 @@
---
- name: Install NGINX
apt:
update_cache: true
name: nginx
register: apt_result
retries: 3
until: apt_result is succeeded
- name: Copy snippets
template:
src: "nginx/snippets/{{ item }}.j2"
dest: "/etc/nginx/snippets/{{ item }}"
owner: root
group: root
mode: 0644
loop:
- options-ssl.conf
- options-proxypass.conf
- name: Copy dhparam
template:
src: letsencrypt/dhparam.j2
dest: /etc/letsencrypt/dhparam
owner: root
group: root
mode: 0644
- name: Disable default site
file:
dest: "/etc/nginx/sites-enabled/default"
state: absent
- name: Copy reverse proxy sites
when: nginx.reverseproxy_sites is defined or nginx.redirect_sites is defined
template:
src: "nginx/sites-available/{{ item }}.j2"
dest: "/etc/nginx/sites-available/{{ item }}"
owner: root
group: root
mode: 0644
loop:
- reverseproxy
- reverseproxy_redirect_dname
- redirect
notify: Reload nginx
- name: Activate reverse proxy sites
when: nginx.reverseproxy_sites is defined or nginx.redirect_sites is defined
file:
src: "/etc/nginx/sites-available/{{ item }}"
dest: "/etc/nginx/sites-enabled/{{ item }}"
owner: root
group: root
state: link
loop:
- reverseproxy
- reverseproxy_redirect_dname
- redirect
notify: Reload nginx
ignore_errors: "{{ ansible_check_mode }}"
- name: Copy service nginx configuration
when: nginx.servers is defined and nginx.servers|length > 0
template:
src: "nginx/sites-available/service.j2"
dest: "/etc/nginx/sites-available/{{ nginx.service_name }}"
owner: root
group: root
mode: 0644
notify: Reload nginx
- name: Activate local nginx service site
when: nginx.servers is defined and nginx.servers|length > 0
file:
src: "/etc/nginx/sites-available/{{ nginx.service_name }}"
dest: "/etc/nginx/sites-enabled/{{ nginx.service_name }}"
owner: root
group: root
state: link
notify: Reload nginx
ignore_errors: "{{ ansible_check_mode }}"
- name: Copy 50x error page
template:
src: www/html/50x.html.j2
dest: /var/www/html/50x.html
owner: www-data
group: www-data
mode: 0644
- name: Copy robots.txt file
when: nginx.deploy_robots_file
template:
src: www/html/robots.txt.j2
dest: /var/www/html/robots.txt
owner: www-data
group: www-data
mode: 0644
- name: Indicate role in motd
template:
src: update-motd.d/05-service.j2
dest: /etc/update-motd.d/05-nginx
mode: 0755
- name: Install passwords
when: nginx.auth_passwd|length > 0
template:
src: nginx/passwd.j2
dest: /etc/nginx/passwd
mode: 0644
- name: Copy 401 error page
when: nginx.auth_passwd|length > 0
template:
src: www/html/401.html.j2
dest: /var/www/html/401.html
owner: www-data
group: www-data
mode: 0644

View file

@ -0,0 +1,8 @@
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS-----

View file

@ -0,0 +1,4 @@
# {{ ansible_managed }}
{% for user, hash in nginx.auth_passwd.items() -%}
{{ user }}: {{ hash }}
{% endfor -%}

View file

@ -0,0 +1,67 @@
# {{ ansible_managed }}
{% for site in nginx.redirect_sites %}
# Redirect http://{{ site.from }} to http://{{ site.to }}
server {
listen 80;
listen [::]:80;
server_name {{ site.from }};
location / {
return 302 http://{{ site.to }}$request_uri;
}
}
# Redirect https://{{ site.from }} to https://{{ site.to }}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ site.from }};
# SSL common conf
include "/etc/nginx/snippets/options-ssl.conf";
location / {
return 302 https://{{ site.to }}$request_uri;
}
}
{% endfor %}
{# Also redirect for DNAMEs #}
{% for dname in nginx.redirect_dnames %}
{% for site in nginx.redirect_sites %}
{% set from = site.from | regex_replace('crans.org', dname) %}
{% if from != site.from %}
# Redirect http://{{ from }} to http://{{ site.to }}
server {
listen 80;
listen [::]:80;
server_name {{ from }};
location / {
return 302 http://{{ site.to }}$request_uri;
}
}
# Redirect https://{{ from }} to https://{{ site.to }}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ from }};
# SSL common conf
include "/etc/nginx/snippets/options-ssl.conf";
location / {
return 302 https://{{ site.to }}$request_uri;
}
}
{% endif %}
{% endfor %}
{% endfor %}

View file

@ -0,0 +1,56 @@
# {{ ansible_managed }}
# Automatic Connection header for WebSocket support
# See http://nginx.org/en/docs/http/websocket.html
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
{% for site in nginx.reverseproxy_sites %}
# Redirect http://{{ site.from }} to https://{{ site.from }}
server {
listen 80;
listen [::]:80;
server_name {{ site.from }};
location / {
return 302 https://$host$request_uri;
}
}
# Reverse proxify https://{{ site.from }} to http://{{ site.to }}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ site.from }};
# SSL common conf
include "/etc/nginx/snippets/options-ssl.conf";
# Log into separate log files
access_log /var/log/nginx/{{ site.from }}.log;
error_log /var/log/nginx/{{ site.from }}_error.log;
# Keep the TCP connection open a bit for faster browsing
keepalive_timeout 70;
# Custom error page
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
set_real_ip_from 10.231.136.0/24;
set_real_ip_from 2a0c:700:0:2::/64;
real_ip_header P-Real-Ip;
location / {
proxy_pass http://{{ site.to }};
include "/etc/nginx/snippets/options-proxypass.conf";
}
}
{% endfor %}

View file

@ -0,0 +1,37 @@
# {{ ansible_managed }}
{% for dname in nginx.redirect_dnames %}
{% for site in nginx.reverseproxy_sites %}
{% set from = site.from | regex_replace('crans.org', dname) %}
{% set to = site.from %}
{% if from != site.from %}
# Redirect http://{{ from }} to http://{{ to }}
server {
listen 80;
listen [::]:80;
server_name {{ from }};
location / {
return 302 http://{{ to }}$request_uri;
}
}
# Redirect https://{{ from }} to https://{{ to }}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ from }};
# SSL common conf
include "/etc/nginx/snippets/options-ssl.conf";
location / {
return 302 https://{{ to }}$request_uri;
}
}
{% endif %}
{% endfor %}
{% endfor %}

View file

@ -0,0 +1,114 @@
# {{ ansible_managed }}
# Automatic Connection header for WebSocket support
# See http://nginx.org/en/docs/http/websocket.html
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
{% for upstream in nginx.upstreams -%}
upstream {{ upstream.name }} {
# Path of the server
server {{ upstream.server }};
}
{% endfor -%}
{% if nginx.default_ssl_server -%}
# Redirect all services to the main site
server {
listen 443 default_server ssl;
listen [::]:443 default_server ssl;
include "/etc/nginx/snippets/options-ssl.conf";
server_name _;
charset utf-8;
# Hide Nginx version
server_tokens off;
location / {
return 302 https://{{ nginx.default_ssl_server }}$request_uri;
}
}
{% endif -%}
{% if nginx.default_server -%}
# Redirect all services to the main site
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
charset utf-8;
# Hide Nginx version
server_tokens off;
location / {
return 302 http://{{ nginx.default_server }}$request_uri;
}
}
{% endif -%}
{% for server in nginx.servers %}
{% if server.ssl is defined and server.ssl -%}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name {{ server.server_name|join(" ") }};
charset utf-8;
# Hide Nginx version
server_tokens off;
location / {
return 302 https://$host$request_uri;
}
}
{% endif -%}
server {
{% if server.ssl is defined and server.ssl -%}
listen 443 ssl;
listen [::]:443 ssl;
include "/etc/nginx/snippets/options-ssl.conf";
{% else -%}
listen 80;
listen [::]:80;
{% endif -%}
server_name {{ server.server_name|join(" ") }};
charset utf-8;
# Hide Nginx version
server_tokens off;
{% if server.root is defined -%}
root {{ server.root }};
{% endif -%}
{% if server.index is defined -%}
index {{ server.index|join(" ") }};
{% endif -%}
{% if server.access_log is defined -%}
access_log {{ server.access_log }};
{% endif -%}
{% if server.error_log is defined -%}
error_log {{ server.error_log }};
{% endif -%}
{% if server.locations is defined -%}
{% for location in server.locations -%}
location {{ location.filter }} {
{% for param in location.params -%}
{{ param }};
{% endfor -%}
}
{% endfor -%}
{% endif -%}
}
{% endfor %}

View file

@ -0,0 +1,18 @@
# {{ ansible_managed }}
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info (^/[^/]*)(.*)$;
# check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
# Let NGINX handle errors
fastcgi_intercept_errors on;
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/var/run/fcgiwrap.socket;

View file

@ -0,0 +1,19 @@
# {{ ansible_managed }}
proxy_redirect off;
proxy_set_header Host $host;
# Pass the real client IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Tell proxified server that we are HTTPS, fix Wordpress
proxy_set_header X-Forwarded-Proto https;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# For Owncloud WebDav
client_max_body_size 10G;

View file

@ -0,0 +1,17 @@
# {{ ansible_managed }}
ssl_certificate {{ nginx.ssl.cert }};
ssl_certificate_key {{ nginx.ssl.cert_key }};
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_dhparam /etc/letsencrypt/dhparam;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Enable OCSP Stapling, point to certificate chain
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate {{ nginx.ssl.trusted_cert }};

View file

@ -0,0 +1,3 @@
#!/usr/bin/tail +14
# {{ ansible_managed }}
> NGINX a été déployé sur cette machine. Voir /etc/nginx/.

View file

@ -0,0 +1,18 @@
{{ ansible_header | comment('xml') }}
<html>
<head>
<title>Accès refusé</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Accès refusé</h1>
<p>
Pour éviter le scan des adresses de diffusions par un robot, cette page demande un identifiant et mot de passe.
</p>
<ul>
<li>Identifiant : <em>Stop</em></li>
<li>Mot de passe : <em>Spam</em></li>
</ul>
</body>
</html>

View file

@ -0,0 +1,63 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>502</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
line-height: 1.2;
margin: 0;
}
html {
color: #888;
display: table;
font-family: sans-serif;
height: 100%;
text-align: center;
width: 100%;
}
body {
display: table-cell;
vertical-align: middle;
margin: 2em auto;
}
a {
color: #888;
text-decoration: underline dotted;
}
h1 {
color: #555;
font-size: 2em;
font-weight: 400;
}
p {
margin: 1em auto;
max-width: 480px;
}
@media only screen and (max-width: 280px) {
body, p {
width: 95%;
}
h1 {
font-size: 1.5em;
margin: 0 0 0.3em;
}
}
</style>
</head>
<body>
<h1>502</h1>
<p>Whoops, le service prend trop de temps à répondre…</p>
<p>Essayez de rafraîchir la page. Si le problème persiste, pensez
à contacter <a href="mailto:{{ nginx.contact }}">{{ nginx.who }}</a>.</p>
</body>
</html>

View file

@ -0,0 +1,4 @@
{{ ansible_header | comment }}
User-agent: *
Disallow: /