Add bastion and certificate jails.

This commit is contained in:
Tom Alexander 2024-07-01 22:01:07 -04:00
parent 566b7dfd0b
commit 9e107d4a75
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
38 changed files with 523 additions and 5 deletions

2
.gitattributes vendored
View File

@ -1,3 +1,5 @@
cargo_credentials.toml filter=git-crypt diff=git-crypt
**/wireguard_configs/** filter=git-crypt diff=git-crypt
*.key filter=git-crypt diff=git-crypt
credentials filter=git-crypt diff=git-crypt
htpasswd filter=git-crypt diff=git-crypt

View File

@ -57,6 +57,13 @@ jail_list:
conf:
src: sftp
fstab: sftp_fstab
- name: bastion
conf:
src: bastion
fstab: fstab_bastion
- name: certificate
conf:
src: certificate
# - name: mumble
# conf:
# src: mumble

View File

@ -0,0 +1 @@
os_flavor: freebsd

View File

@ -0,0 +1 @@
os_flavor: freebsd

View File

@ -6,3 +6,5 @@ nat_dhcp@172.16.16.2 ansible_connection=sshjail
admin_git ansible_ssh_host=admin_git@10.217.2.1 ansible_connection=sshjail
public_dns ansible_ssh_host=public_dns@10.217.2.1 ansible_connection=sshjail
sftp ansible_ssh_host=sftp@homeserver ansible_connection=sshjail
bastion ansible_ssh_host=bastion@homeserver ansible_connection=sshjail
certificate ansible_ssh_host=certificate@homeserver ansible_connection=sshjail

View File

@ -143,3 +143,14 @@
- users
- sftp
- hosts: bastion
vars:
ansible_become: True
roles:
- jail_bastion
- hosts: certificate
vars:
ansible_become: True
roles:
- jail_certificate

View File

@ -17,23 +17,32 @@ unifi_ports = "{ 8443 3478 10001 8080 1900 8843 8880 6789 5514 }"
# options
set skip on lo
# queueing
# altq on wlan0 cbq queue { def, stuff }
# queue def cbq(default borrow)
# queue stuff bandwidth 8Mb cbq { dagger }
# queue dagger cbq(borrow)
# redirections
nat pass on $ext_if inet from $jail_nat_v4 to $not_jail_nat_v4 -> (wlan0)
rdr pass on $not_ext_if proto {tcp, udp} from any to 10.215.1.1 port 53 -> 1.1.1.1 port 53
rdr pass on $not_ext_if proto {tcp, udp} from any to 10.215.1.1 port 53 -> 172.16.0.1 port 53
# cloak
nat pass on $ext_if inet from 10.215.2.0/24 to !10.215.2.0/24 -> (wlan0)
rdr pass on $not_ext_if proto {tcp, udp} from any to 10.215.2.1 port 53 -> 1.1.1.1 port 53
rdr pass on $not_ext_if proto {tcp, udp} from any to 10.215.2.1 port 53 -> 172.16.0.1 port 53
# bastion
rdr pass on $ext_if inet proto tcp from { any, !10.215.1.0/24, !10.215.2.0/24 } to any port 8081 -> 10.215.1.217 port 443
nat pass on jail_nat proto {tcp, udp} from any to 10.215.1.217 port 443 -> 10.215.1.1
nat pass on restricted_nat proto {tcp, udp} from 10.215.1.217/32 to 10.215.2.2 port 8081 -> 10.215.2.1
# cloak -> dagger
rdr pass on $ext_if inet proto tcp from $not_restricted_nat_v4 to any port 8081 -> 10.215.2.2 port 8081
nat pass on restricted_nat proto {tcp, udp} from any to 10.215.2.2 port 8081 -> 10.215.2.1
# cloak -> olddagger
rdr pass on $ext_if inet proto tcp from $not_restricted_nat_v4 to any port 8082 -> 10.215.2.2 port 8082
nat pass on restricted_nat proto {tcp, udp} from any to 10.215.2.2 port 8082 -> 10.215.2.1
# -> sftp
# TODO: Limit bandwidth for sftp
rdr pass on $ext_if inet proto tcp from $not_jail_nat_v4 to any port 8022 -> 10.215.1.216 port 22
nat pass on jail_nat proto {tcp, udp} from any to 10.215.1.216 port 22 -> 10.215.1.1
@ -51,6 +60,7 @@ pass out on jail_nat from $jail_nat_v4
pass out on jail_nat proto {udp, tcp} from any to 10.215.1.202 port $unifi_ports
pass out on restricted_nat proto {udp, tcp} from any to 10.215.2.2 port 8081
# TODO: limit bandwidth for dagger here
pass in on restricted_nat proto {udp, tcp} from any to any port { 53 51820 }
# We pass on the interfaces listed in allow rather than skipping on

View File

@ -0,0 +1,4 @@
tmpfs /jail/bastion/tmp tmpfs rw,mode=777 0 0
tmpfs /jail/bastion/var/run tmpfs rw,mode=755 0 0
/jail/certificate/usr/local/etc/letsencrypt/archive/stuff.fizz.buzz /jail/bastion/stuff.fizz.buzz nullfs ro,noexec 0 0

View File

@ -0,0 +1,15 @@
bastion {
path = "/jail/${name}";
vnet;
exec.prestart += "/usr/local/bin/jail_netgraph_bridge start jail_nat jail${name} 10.215.1.1/24";
exec.poststop += "/usr/local/bin/jail_netgraph_bridge stop jail_nat jail${name}";
vnet.interface += "jail${name}";
devfs_ruleset = 14;
mount.devfs;
mount.fstab = "/etc/fstab.${name}";
exec.start += "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown jail";
exec.consolelog = "/var/log/jail_${name}_console.log";
}

View File

@ -0,0 +1,15 @@
certificate {
path = "/jail/${name}";
vnet;
exec.prestart += "/usr/local/bin/jail_netgraph_bridge start jail_nat jail${name} 10.215.1.1/24";
exec.poststop += "/usr/local/bin/jail_netgraph_bridge stop jail_nat jail${name}";
vnet.interface += "jail${name}";
devfs_ruleset = 14;
mount.devfs;
mount.fstab = "/etc/fstab.${name}";
exec.start += "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown jail";
exec.consolelog = "/var/log/jail_${name}_console.log";
}

View File

@ -0,0 +1,12 @@
# Enable HTTP Strict Transport Security (HSTS) to force clients to
# always connect via HTTPS (do not use if only testing)
add_header Strict-Transport-Security "max-age=31536000;" always;
# Enable cross-site filter (XSS) and tell browser to block detected
# attacks
add_header X-XSS-Protection "1; mode=block" always;
# Prevent some browsers from MIME-sniffing a response away from the
# declared Content-Type
add_header X-Content-Type-Options "nosniff" always;
# Disallow the site to be rendered within a frame (clickjacking
# protection)
add_header X-Frame-Options "DENY" always;

Binary file not shown.

View File

@ -0,0 +1,2 @@
# logfilename [owner:group] mode count size when flags [/pid_file] [sig_num]
/var/log/nginx/*.log 640 5 1000 @T00 GYC /var/run/nginx.pid SIGUSR1

View File

@ -0,0 +1,52 @@
worker_processes auto;
user www www;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
types {
text/plain log;
}
sendfile on;
tcp_nopush on;
tcp_nodelay on;
gzip on;
include conf.d/headers.include;
upstream inner {
server 10.215.2.2:8081;
keepalive 4;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name stuff.fizz.buzz;
include conf.d/tls_settings.include;
# RSA
ssl_certificate /stuff.fizz.buzz/fullchain1.pem;
ssl_certificate_key /stuff.fizz.buzz/privkey1.pem;
# Nginx by default only allows file uploads up to 1M in size
client_max_body_size 50M;
location / {
auth_basic "Stuff";
auth_basic_user_file conf.d/htpasswd;
proxy_pass http://inner;
include conf.d/proxy.include;
}
}
}

View File

@ -0,0 +1 @@
nginx_enable="YES"

View File

@ -0,0 +1,7 @@
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Settings for keepalive module for upstreams
proxy_http_version 1.1;
proxy_set_header Connection "";

View File

@ -0,0 +1,3 @@
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;

View File

@ -0,0 +1,2 @@
dependencies:
- syslog

View File

@ -0,0 +1,55 @@
# - name: Create directories
# file:
# name: "{{ item }}"
# state: directory
# mode: 0755
# owner: root
# group: wheel
# loop:
# - /foo/bar
# - name: Install scripts
# copy:
# src: "files/{{ item.src }}"
# dest: "{{ item.dest }}"
# mode: 0755
# owner: root
# group: wheel
# loop:
# - src: foo.bash
# dest: /usr/local/bin/foo
# - name: Install Configuration
# copy:
# src: "files/{{ item.src }}"
# dest: "{{ item.dest }}"
# mode: 0600
# owner: root
# group: wheel
# loop:
# - src: foo.conf
# dest: /usr/local/etc/foo.conf
# - name: Clone Source
# git:
# repo: "https://foo.bar/baz.git"
# dest: /foo/bar
# version: "v1.0.2"
# force: true
# diff: false
- import_tasks: tasks/freebsd.yaml
when: 'os_flavor == "freebsd"'
- import_tasks: tasks/linux.yaml
when: 'os_flavor == "linux"'
# - include_tasks:
# file: tasks/peruser.yaml
# apply:
# become: yes
# become_user: "{{ initialize_user }}"
# when: users is defined
# loop: "{{ users | dict2items | community.general.json_query('[?value.initialize==`true`].key') }}"
# loop_control:
# loop_var: initialize_user

View File

@ -0,0 +1,81 @@
- name: Create www group
group:
name: www
- name: Create www user
user:
name: www
home: /srv/http
createhome: false
group: www
- name: Create directories
file:
name: "{{ item }}"
state: directory
mode: 0755
owner: root
group: wheel
loop:
- /stuff.fizz.buzz
- /etc/rc.conf.d
- /usr/local/etc/nginx/conf.d
- name: Create directories
file:
name: "{{ item }}"
state: directory
mode: 0755
owner: www
group: www
loop:
- /srv/http
- name: Install packages
package:
name:
- nginx
state: present
# validate fails because nginx config relies on a local mime.types
- name: Install Configuration
copy:
src: "files/{{ item.src }}"
dest: "{{ item.dest }}"
mode: 0644
owner: root
group: wheel
loop:
- src: nginx.conf
dest: /usr/local/etc/nginx/nginx.conf
- src: headers.include
dest: /usr/local/etc/nginx/conf.d/headers.include
- src: proxy.include
dest: /usr/local/etc/nginx/conf.d/proxy.include
- src: tls_settings.include
dest: /usr/local/etc/nginx/conf.d/tls_settings.include
# Generate htpasswd with `htpasswd -c files/htpasswd user1`
# or `printf "USER:$(openssl passwd)\n" >> files/htpasswd`
- src: htpasswd
dest: /usr/local/etc/nginx/conf.d/htpasswd
- name: Install newsyslog configuration
copy:
src: "files/{{ item.src }}"
dest: "{{ item.dest }}"
mode: 0600
owner: root
group: wheel
loop:
- src: newsyslog.conf
dest: /usr/local/etc/newsyslog.conf.d/nginx.conf
- name: Install service configuration
copy:
src: "files/{{ item }}_rc.conf"
dest: "/etc/rc.conf.d/{{ item }}"
mode: 0644
owner: root
group: wheel
loop:
- nginx

View File

@ -0,0 +1,29 @@
# - name: Build aur packages
# register: buildaur
# become_user: "{{ build_user.name }}"
# command: "aurutils-sync --no-view {{ item }}"
# args:
# creates: "/var/cache/pacman/custom/{{ item }}-*.pkg.tar.*"
# loop:
# - foo
# - name: Update cache
# when: buildaur.changed
# pacman:
# name: []
# state: present
# update_cache: true
# - name: Install packages
# package:
# name:
# - foo
# state: present
# - name: Enable services
# systemd:
# enabled: yes
# name: "{{ item }}"
# daemon_reload: yes
# loop:
# - foo.service

View File

@ -0,0 +1,2 @@
- import_tasks: tasks/common.yaml
# when: foo is defined

View File

@ -0,0 +1,29 @@
- include_role:
name: per_user
# - name: Create directories
# file:
# name: "{{ account_homedir.stdout }}/{{ item }}"
# state: directory
# mode: 0700
# owner: "{{ account_name.stdout }}"
# group: "{{ group_name.stdout }}"
# loop:
# - ".config/foo"
# - name: Copy files
# copy:
# src: "files/{{ item.src }}"
# dest: "{{ account_homedir.stdout }}/{{ item.dest }}"
# mode: 0600
# owner: "{{ account_name.stdout }}"
# group: "{{ group_name.stdout }}"
# loop:
# - src: foo.conf
# dest: .config/foo/foo.conf
- import_tasks: tasks/peruser_freebsd.yaml
when: 'os_flavor == "freebsd"'
- import_tasks: tasks/peruser_linux.yaml
when: 'os_flavor == "linux"'

Binary file not shown.

View File

@ -0,0 +1,2 @@
# dependencies:
# - users

View File

@ -0,0 +1,55 @@
# - name: Create directories
# file:
# name: "{{ item }}"
# state: directory
# mode: 0755
# owner: root
# group: wheel
# loop:
# - /foo/bar
# - name: Install scripts
# copy:
# src: "files/{{ item.src }}"
# dest: "{{ item.dest }}"
# mode: 0755
# owner: root
# group: wheel
# loop:
# - src: foo.bash
# dest: /usr/local/bin/foo
# - name: Install Configuration
# copy:
# src: "files/{{ item.src }}"
# dest: "{{ item.dest }}"
# mode: 0600
# owner: root
# group: wheel
# loop:
# - src: foo.conf
# dest: /usr/local/etc/foo.conf
# - name: Clone Source
# git:
# repo: "https://foo.bar/baz.git"
# dest: /foo/bar
# version: "v1.0.2"
# force: true
# diff: false
- import_tasks: tasks/freebsd.yaml
when: 'os_flavor == "freebsd"'
- import_tasks: tasks/linux.yaml
when: 'os_flavor == "linux"'
# - include_tasks:
# file: tasks/peruser.yaml
# apply:
# become: yes
# become_user: "{{ initialize_user }}"
# when: users is defined
# loop: "{{ users | dict2items | community.general.json_query('[?value.initialize==`true`].key') }}"
# loop_control:
# loop_var: initialize_user

View File

@ -0,0 +1,44 @@
- name: Install packages
package:
name:
- py311-certbot
- py311-certbot-dns-rfc2136
state: present
- name: Enable periodic renew
community.general.sysrc:
name: weekly_certbot_enable
value: "YES"
path: /etc/periodic.conf.local
- name: Create directories
file:
name: "{{ item }}"
state: directory
mode: 0755
owner: root
group: wheel
loop:
- /certbot
- name: Install Configuration
diff: false
copy:
src: "files/{{ item.src }}"
dest: "{{ item.dest }}"
mode: 0600
owner: root
group: wheel
loop:
- src: credentials
dest: /certbot/credentials
# For each domain, run:
# certbot certonly -v --register-unsafely-without-email \
# --dns-rfc2136 \
# --dns-rfc2136-credentials /certbot/credentials \
# --dns-rfc2136-propagation-seconds 400 \
# -d example.com \
# -d www.example.com
#
# Add --test-cert for staging environment

View File

@ -0,0 +1,29 @@
# - name: Build aur packages
# register: buildaur
# become_user: "{{ build_user.name }}"
# command: "aurutils-sync --no-view {{ item }}"
# args:
# creates: "/var/cache/pacman/custom/{{ item }}-*.pkg.tar.*"
# loop:
# - foo
# - name: Update cache
# when: buildaur.changed
# pacman:
# name: []
# state: present
# update_cache: true
# - name: Install packages
# package:
# name:
# - foo
# state: present
# - name: Enable services
# systemd:
# enabled: yes
# name: "{{ item }}"
# daemon_reload: yes
# loop:
# - foo.service

View File

@ -0,0 +1,2 @@
- import_tasks: tasks/common.yaml
# when: foo is defined

View File

@ -0,0 +1,29 @@
- include_role:
name: per_user
# - name: Create directories
# file:
# name: "{{ account_homedir.stdout }}/{{ item }}"
# state: directory
# mode: 0700
# owner: "{{ account_name.stdout }}"
# group: "{{ group_name.stdout }}"
# loop:
# - ".config/foo"
# - name: Copy files
# copy:
# src: "files/{{ item.src }}"
# dest: "{{ account_homedir.stdout }}/{{ item.dest }}"
# mode: 0600
# owner: "{{ account_name.stdout }}"
# group: "{{ group_name.stdout }}"
# loop:
# - src: foo.conf
# dest: .config/foo/foo.conf
- import_tasks: tasks/peruser_freebsd.yaml
when: 'os_flavor == "freebsd"'
- import_tasks: tasks/peruser_linux.yaml
when: 'os_flavor == "linux"'

View File

@ -83,6 +83,11 @@
// sftp
"hw-address": "58:9c:fc:10:ff:ab",
"ip-address": "10.215.1.216"
},
{
// bastion
"hw-address": "58:9c:fc:10:ff:a2",
"ip-address": "10.215.1.217"
}
]
}

View File

@ -71,3 +71,4 @@ _caldavs._tcp IN SRV 0 1 443 caldav.fastmail.com
home IN A 68.197.252.22
opstunnel IN CNAME home.fizz.buzz.
stream IN CNAME home.fizz.buzz.
stuff IN CNAME home.fizz.buzz.

View File

@ -110,6 +110,10 @@
command: pdnsutil add-meta fizz.buzz ALLOW-DNSUPDATE-FROM 10.215.1.0/24
when: '"10.215.1.0/24" not in allowdnsupdatefrom.stdout'
- name: Allow IP addresses
command: pdnsutil add-meta fizz.buzz ALLOW-DNSUPDATE-FROM 68.197.252.15/32
when: '"68.197.252.15/32" not in allowdnsupdatefrom.stdout'
- name: Allow AXFR from the externaldns tsig key
command: pdnsutil add-meta fizz.buzz TSIG-ALLOW-AXFR externaldns
when: '"externaldns" not in tsigaxfr.stdout'

View File

@ -30,6 +30,10 @@ elif [ "$target" = "jail_homeserver_nat_dhcp" ]; then
ansible-playbook -v -i environments/jail playbook.yaml --diff --limit homeserver_nat_dhcp "${@}"
elif [ "$target" = "sftp" ]; then
ansible-playbook -v -i environments/jail playbook.yaml --diff --limit sftp "${@}"
elif [ "$target" = "certificate" ]; then
ansible-playbook -v -i environments/jail playbook.yaml --diff --limit certificate "${@}"
elif [ "$target" = "bastion" ]; then
ansible-playbook -v -i environments/jail playbook.yaml --diff --limit bastion "${@}"
elif [ "$target" = "vm_poudriereodo" ]; then
ansible-playbook -v -i environments/vm playbook.yaml --diff --limit poudriereodo "${@}"
elif [ "$target" = "vm_poudrieremrmanager" ]; then