add nginx, sshd, ssl roles
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
- name: install package
|
||||
ansible.builtin.apt:
|
||||
name: "{{ item }}"
|
||||
update_cache: true
|
||||
loop: "{{ apt }}"
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
- name: include apt install
|
||||
ansible.builtin.include_tasks: apt.yml
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: install certbot
|
||||
ansible.builtin.apt:
|
||||
name: certbot
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: issue certificate if missing
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
certbot certonly --standalone
|
||||
--non-interactive --agree-tos
|
||||
--register-unsafely-without-email
|
||||
--pre-hook "{{ item.pre_hook }}"
|
||||
--post-hook "{{ item.post_hook }}"
|
||||
{{ item.domains | map('regex_replace', '^(.*)$', '-d \1') | join(' ') }}
|
||||
creates: "/etc/letsencrypt/live/{{ item.domains[0] }}/fullchain.pem"
|
||||
loop: "{{ certbot_certs }}"
|
||||
loop_control:
|
||||
label: "{{ item.domains | join(',') }}"
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: install wireguard-tools
|
||||
- name: install certbot
|
||||
ansible.builtin.apt:
|
||||
name: wireguard-tools
|
||||
name: certbot
|
||||
state: latest
|
||||
update_cache: true
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: include wireguard-tools install
|
||||
- name: include certbot install
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: include wireguard-tools configurure
|
||||
- name: include certbot configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
@@ -1,5 +1,5 @@
|
||||
interface=lo
|
||||
interface=eth0
|
||||
interface=br-eth0
|
||||
interface=eth0.2
|
||||
interface=eth0.3
|
||||
interface=eth0.4
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in dnsmasq_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% set ip = client.container_ip | default(client.ansible_host | default(none)) %}
|
||||
{% if client['dhcp-host'] is defined and client['dhcp-host'] and ip %}
|
||||
{% set entries = client['dhcp-host'] if (client['dhcp-host'] is iterable and client['dhcp-host'] is not string) else [client['dhcp-host']] %}
|
||||
{% for entry in entries %}
|
||||
{% if entry.mac %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% set ip = client.container_ip | default(client.ansible_host | default(none)) %}
|
||||
{% if client['dhcp-host'] is defined and client['dhcp-host'] and ip %}
|
||||
{% set entries = client['dhcp-host'] if (client['dhcp-host'] is iterable and client['dhcp-host'] is not string) else [client['dhcp-host']] %}
|
||||
{% for entry in entries %}
|
||||
{% if entry.mac %}
|
||||
dhcp-host={{ entry.mac }},{{ ip }},{{ item }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in dnsmasq_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'dnsmasq' in client and client.dnsmasq %}
|
||||
{% set default_ip = client.container_ip | default(client.ansible_host | default(none)) %}
|
||||
{% set domains = client.dnsmasq if (client.dnsmasq is iterable and client.dnsmasq is not string) else [client.dnsmasq] %}
|
||||
{% for d in domains %}
|
||||
{% set entry = d if (d is mapping) else {'name': d} %}
|
||||
{% set ip = entry.ip | default(default_ip) %}
|
||||
{% if ip %}
|
||||
{% for entry in hostvars[item].dnsmasq | default([]) %}
|
||||
{% set ip = entry.ip | default(hostvars[entry.ip_from].container_ip if entry.ip_from is defined else none) %}
|
||||
{% if ip %}
|
||||
host-record={{ entry.name }},{{ ip }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in dnsmasq_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% set ip = client.container_ip | default(client.ansible_host | default(none)) %}
|
||||
{% if ip %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% set ip = client.container_ip | default(client.ansible_host | default(none)) %}
|
||||
{% if ip %}
|
||||
host-record={{ item }},{{ item }}.lan,{{ ip }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: ensure local output directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ openvpn_client_bundle_dir }}/{{ item.0.name }}"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
loop: "{{ openvpn_instances | subelements('clients') }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: render standalone client bundles
|
||||
ansible.builtin.template:
|
||||
src: "{{ role_path }}/templates/client-certs/{{ item.0.name }}.conf.j2"
|
||||
dest: "{{ openvpn_client_bundle_dir }}/{{ item.0.name }}/{{ item.1.name }}.ovpn"
|
||||
mode: '0600'
|
||||
loop: "{{ openvpn_instances | subelements('clients') }}"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
@@ -0,0 +1,82 @@
|
||||
---
|
||||
- name: prepare list of client certificates
|
||||
ansible.builtin.set_fact:
|
||||
cert_list: "{{ cert_list | default([]) + [ {'instance': item.0.name, 'pki_dir': item.0.pki_dir, 'client': item.1} ] }}"
|
||||
loop: "{{ openvpn_instances | subelements('clients') }}"
|
||||
|
||||
- name: ensure local PKI directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.pki_dir }}"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
loop: "{{ openvpn_instances }}"
|
||||
|
||||
- name: init pki if missing
|
||||
ansible.builtin.command:
|
||||
cmd: /opt/easy-rsa/easyrsa --batch init-pki
|
||||
creates: "{{ item.pki_dir }}/private"
|
||||
environment:
|
||||
EASYRSA_PKI: "{{ item.pki_dir }}"
|
||||
loop: "{{ openvpn_instances }}"
|
||||
|
||||
- name: build ca if missing
|
||||
ansible.builtin.command:
|
||||
cmd: /opt/easy-rsa/easyrsa --batch build-ca nopass
|
||||
creates: "{{ item.pki_dir }}/ca.crt"
|
||||
environment:
|
||||
EASYRSA_PKI: "{{ item.pki_dir }}"
|
||||
EASYRSA_REQ_CN: "CA-{{ item.name }}"
|
||||
loop: "{{ openvpn_instances }}"
|
||||
|
||||
- name: build server cert if missing
|
||||
ansible.builtin.command:
|
||||
cmd: /opt/easy-rsa/easyrsa --batch build-server-full server nopass
|
||||
creates: "{{ item.pki_dir }}/issued/server.crt"
|
||||
environment:
|
||||
EASYRSA_PKI: "{{ item.pki_dir }}"
|
||||
loop: "{{ openvpn_instances }}"
|
||||
|
||||
- name: generate dh params if missing
|
||||
ansible.builtin.command:
|
||||
cmd: /opt/easy-rsa/easyrsa gen-dh
|
||||
creates: "{{ item.pki_dir }}/dh.pem"
|
||||
environment:
|
||||
EASYRSA_PKI: "{{ item.pki_dir }}"
|
||||
loop: "{{ openvpn_instances }}"
|
||||
|
||||
- name: check client certificates validity
|
||||
ansible.builtin.command:
|
||||
cmd: "openssl x509 -checkend 2592000 -in {{ item.pki_dir }}/issued/{{ item.client.name }}.crt"
|
||||
register: cert_check
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
loop: "{{ cert_list }}"
|
||||
|
||||
- name: remove old cert file before reissue
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.item.pki_dir }}/issued/{{ item.item.client.name }}.crt"
|
||||
state: absent
|
||||
loop: "{{ cert_check.results }}"
|
||||
when: item.rc != 0
|
||||
|
||||
- name: remove old req file before reissue
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.item.pki_dir }}/reqs/{{ item.item.client.name }}.req"
|
||||
state: absent
|
||||
loop: "{{ cert_check.results }}"
|
||||
when: item.rc != 0
|
||||
|
||||
- name: remove old key file before reissue
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.item.pki_dir }}/private/{{ item.item.client.name }}.key"
|
||||
state: absent
|
||||
loop: "{{ cert_check.results }}"
|
||||
when: item.rc != 0
|
||||
|
||||
- name: issue or renew client certificates
|
||||
ansible.builtin.command:
|
||||
cmd: /opt/easy-rsa/easyrsa --batch build-client-full "{{ item.item.client.name }}" nopass
|
||||
environment:
|
||||
EASYRSA_PKI: "{{ item.item.pki_dir }}"
|
||||
when: item.rc != 0
|
||||
loop: "{{ cert_check.results }}"
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
- name: get latest easy-rsa release info
|
||||
ansible.builtin.uri:
|
||||
url: https://api.github.com/repos/OpenVPN/easy-rsa/releases/latest
|
||||
return_content: true
|
||||
register: easyrsa_release
|
||||
run_once: true
|
||||
check_mode: false
|
||||
|
||||
- name: set current easy-rsa version
|
||||
ansible.builtin.set_fact:
|
||||
easyrsa_version: "{{ easyrsa_release.json.tag_name | replace('v', '') }}"
|
||||
easyrsa_asset_url: "{{ easyrsa_release.json.assets | selectattr('name', 'search', 'EasyRSA.*\\.tgz') | map(attribute='browser_download_url') | first }}"
|
||||
|
||||
- name: check easy-rsa installed version
|
||||
ansible.builtin.command: /opt/easy-rsa/easyrsa version
|
||||
register: easyrsa_current_version
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: ensure easy-rsa directory exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/easy-rsa
|
||||
state: directory
|
||||
mode: '0755'
|
||||
check_mode: false
|
||||
|
||||
- name: update easy-rsa
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ easyrsa_asset_url }}"
|
||||
dest: /opt/easy-rsa
|
||||
remote_src: true
|
||||
extra_opts:
|
||||
- --strip-components=1
|
||||
when: easyrsa_version not in (easyrsa_current_version.stdout | default(''))
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: include install
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: include configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
|
||||
- name: include client-certs.yml
|
||||
ansible.builtin.include_tasks: client-certs.yml
|
||||
@@ -0,0 +1,26 @@
|
||||
client
|
||||
dev tap0
|
||||
proto tcp
|
||||
remote 127.0.0.1 1195
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
remote-cert-tls server
|
||||
auth SHA256
|
||||
cipher AES-256-GCM
|
||||
verb 3
|
||||
{% if item.1.ip is defined %}
|
||||
route-metric {{ item.1.route_metric | default(50) }}
|
||||
script-security 2
|
||||
up "C:\\Windows\\System32\\netsh.exe interface ip set address name="OpenVPN TAP-Windows6" static {{ item.1.ip }} 255.255.255.0"
|
||||
{% endif %}
|
||||
<ca>
|
||||
{{ lookup('file', item.0.pki_dir + '/ca.crt') }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ lookup('file', item.0.pki_dir + '/issued/' + item.1.name + '.crt') }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ lookup('file', item.0.pki_dir + '/private/' + item.1.name + '.key') }}
|
||||
</key>
|
||||
@@ -0,0 +1,21 @@
|
||||
client
|
||||
dev tun0
|
||||
proto tcp
|
||||
remote 127.0.0.1 1194
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
remote-cert-tls server
|
||||
auth SHA256
|
||||
cipher AES-256-GCM
|
||||
verb 3
|
||||
<ca>
|
||||
{{ lookup('file', item.0.pki_dir + '/ca.crt') }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ lookup('file', item.0.pki_dir + '/issued/' + item.1.name + '.crt') }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ lookup('file', item.0.pki_dir + '/private/' + item.1.name + '.key') }}
|
||||
</key>
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: validate haproxy config
|
||||
ansible.builtin.command: haproxy -c -f /etc/haproxy/haproxy.cfg
|
||||
changed_when: false
|
||||
listen: restart haproxy
|
||||
|
||||
- name: restart haproxy systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: haproxy
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
listen: restart haproxy
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: render haproxy config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/haproxy/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
loop: "{{ query('fileglob', role_path + '/templates/' + inventory_hostname + '/*.cfg.j2') }}"
|
||||
notify: restart haproxy
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: install haproxy
|
||||
ansible.builtin.apt:
|
||||
name: haproxy
|
||||
state: latest
|
||||
update_cache: true
|
||||
@@ -0,0 +1,90 @@
|
||||
global
|
||||
log /dev/log local2
|
||||
chroot /var/lib/haproxy
|
||||
maxconn 4000
|
||||
user haproxy
|
||||
group haproxy
|
||||
daemon
|
||||
stats socket /var/lib/haproxy/stats mode 660 level admin
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode tcp
|
||||
option tcplog
|
||||
option dontlognull
|
||||
retries 3
|
||||
timeout connect 5s
|
||||
timeout client 1h
|
||||
timeout server 1h
|
||||
timeout check 10s
|
||||
|
||||
frontend http_frontend
|
||||
bind 127.0.0.1:10080
|
||||
mode http
|
||||
option httplog
|
||||
acl host_dttx hdr_end(host) -m end dttx.ru
|
||||
use_backend dttx_http_srv if host_dttx
|
||||
default_backend oyacoi_http_srv
|
||||
|
||||
backend oyacoi_http_srv
|
||||
mode http
|
||||
server oyacoi_srv {{ hostvars['nginx']['container_ip'] }}:81 send-proxy-v2
|
||||
|
||||
backend dttx_http_srv
|
||||
mode http
|
||||
server dttx_srv {{ hostvars['rbpi4']['container_ip'] }}:81 send-proxy-v2
|
||||
|
||||
frontend https_frontend
|
||||
bind 127.0.0.1:10443
|
||||
mode tcp
|
||||
option tcplog
|
||||
tcp-request inspect-delay 5s
|
||||
tcp-request content accept if { req_ssl_hello_type 1 }
|
||||
acl host_dttx req_ssl_sni -m end dttx.ru
|
||||
acl host_telemt req_ssl_sni -m end regionculture.ru
|
||||
use_backend dttx_https_srv if host_dttx
|
||||
use_backend telemt_https_srv if host_telemt
|
||||
default_backend oyacoi_https_srv
|
||||
|
||||
backend oyacoi_https_srv
|
||||
mode tcp
|
||||
server nginx_srv {{ hostvars['nginx']['container_ip'] }}:444 send-proxy-v2
|
||||
|
||||
backend dttx_https_srv
|
||||
mode tcp
|
||||
server dttx_srv {{ hostvars['rbpi4']['container_ip'] }}:444 send-proxy-v2
|
||||
|
||||
backend telemt_https_srv
|
||||
mode tcp
|
||||
option tcp-check
|
||||
server telemt_srv {{ hostvars['vector']['container_ip'] }}:8080 check send-proxy-v2
|
||||
server telemt_srv_backup {{ hostvars['dev']['container_ip'] }}:8080 check send-proxy-v2 backup
|
||||
|
||||
listen mcsmanager_service
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:24444
|
||||
mode tcp
|
||||
server mcs_srv {{ hostvars['mcsmanager']['container_ip'] }}:24445 send-proxy-v2
|
||||
|
||||
listen xmpp_c2s
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:5222
|
||||
server prosody_srv {{ hostvars['prosody']['container_ip'] }}:5222
|
||||
|
||||
listen xmpp_legacy_ssl
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:5223
|
||||
server prosody_srv {{ hostvars['prosody']['container_ip'] }}:5223
|
||||
|
||||
listen xmpp_s2s
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:5269
|
||||
server prosody_srv {{ hostvars['prosody']['container_ip'] }}:5269
|
||||
|
||||
listen prosody_proxy65
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:5000
|
||||
server prosody_srv {{ hostvars['prosody']['container_ip'] }}:5000
|
||||
|
||||
listen prosody_components
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:5270
|
||||
server prosody_srv {{ hostvars['prosody']['container_ip'] }}:5270
|
||||
|
||||
listen prosody_bosh_http
|
||||
bind {{ hostvars['liqueur']['container_ip'] }}:5280
|
||||
server prosody_srv {{ hostvars['prosody']['container_ip'] }}:5280
|
||||
@@ -0,0 +1,50 @@
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
post-up ip rule add fwmark 0x1 lookup 100 2>/dev/null || true
|
||||
post-up ip route add local 0.0.0.0/0 dev lo table 100 2>/dev/null || true
|
||||
pre-down ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null || true
|
||||
pre-down ip rule del fwmark 0x1 lookup 100 2>/dev/null || true
|
||||
|
||||
auto br-eth0
|
||||
iface br-eth0 inet static
|
||||
address 10.1.0.1/24
|
||||
bridge_ports eth0 tap0
|
||||
bridge_stp off
|
||||
pre-up ip tuntap add dev tap0 mode tap || true
|
||||
post-down ip tuntap del dev tap0 mode tap || true
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet manual
|
||||
|
||||
auto eth0.2
|
||||
iface eth0.2 inet static
|
||||
address 10.2.0.1/24
|
||||
vlan-raw-device eth0
|
||||
|
||||
auto eth0.3
|
||||
iface eth0.3 inet static
|
||||
address 10.3.0.1/24
|
||||
vlan-raw-device eth0
|
||||
|
||||
auto eth0.4
|
||||
iface eth0.4 inet static
|
||||
address 10.4.0.1/24
|
||||
vlan-raw-device eth0
|
||||
|
||||
auto eth0.10
|
||||
iface eth0.10 inet static
|
||||
address 10.10.0.1/24
|
||||
vlan-raw-device eth0
|
||||
|
||||
auto eth0.11
|
||||
iface eth0.11 inet static
|
||||
address 10.11.0.1/24
|
||||
vlan-raw-device eth0
|
||||
|
||||
auto eth0.12
|
||||
iface eth0.12 inet static
|
||||
address 10.12.0.1/24
|
||||
vlan-raw-device eth0
|
||||
|
||||
auto eth1
|
||||
iface eth1 inet dhcp
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: deploy ifupdown interfaces config
|
||||
ansible.builtin.template:
|
||||
src: interfaces
|
||||
- name: deploy ifupdown interfaces
|
||||
ansible.builtin.copy:
|
||||
src: "{{ inventory_hostname }}/interfaces"
|
||||
dest: /etc/network/interfaces
|
||||
owner: root
|
||||
group: root
|
||||
@@ -1,3 +1,7 @@
|
||||
---
|
||||
- name: include network configuration
|
||||
include_tasks: network.yml
|
||||
- name: include configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
|
||||
- name: include prerequisites
|
||||
ansible.builtin.include_tasks: prerequisites.yml
|
||||
tags: ifupdown2_prereqs
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: install bridge-utils
|
||||
ansible.builtin.package:
|
||||
name: bridge-utils
|
||||
state: present
|
||||
register: bridge_utils_install
|
||||
|
||||
- name: ensure rt_tables.d directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/iproute2/rt_tables.d
|
||||
state: directory
|
||||
mode: "0755"
|
||||
register: rt_tables_dir
|
||||
|
||||
- name: reload ifupdown2
|
||||
ansible.builtin.command: ifreload -a
|
||||
when: bridge_utils_install.changed or rt_tables_dir.changed
|
||||
@@ -1,20 +0,0 @@
|
||||
{% for item in ifupdown2 %}
|
||||
auto {{ item.iface }}
|
||||
iface {{ item.iface }}{% if item.method is defined %} inet {{ item.method }}
|
||||
{% endif %}
|
||||
|
||||
{% if item.address is defined %}
|
||||
address {{ item.address }}
|
||||
{% endif %}
|
||||
{% if item['vlan-raw-device'] is defined %}
|
||||
vlan-raw-device {{ item['vlan-raw-device'] }}
|
||||
{% endif %}
|
||||
{% if item.routing is defined %}
|
||||
{% for route in item.routing %}
|
||||
{{ route }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if not loop.last %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -5,14 +5,6 @@
|
||||
state: present
|
||||
loop: "{{ locales_list }}"
|
||||
|
||||
- name: configure /etc/default/locale
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/default/locale
|
||||
content: LANG={{ locale_default }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: configure /etc/locale.conf
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/locale.conf
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/var/log/xray-core/*.log {
|
||||
daily
|
||||
rotate 4
|
||||
compress
|
||||
delaycompress
|
||||
missingok
|
||||
notifempty
|
||||
copytruncate
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
---
|
||||
- name: deploy logrotate config
|
||||
ansible.builtin.template:
|
||||
src: logrotate.conf.j2
|
||||
dest: "/etc/logrotate.d/{{ item.name }}"
|
||||
mode: "0644"
|
||||
loop: "{{ logrotate }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ inventory_hostname }}/"
|
||||
dest: "/etc/logrotate.d/"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{{ item.paths | join(' ') }} {
|
||||
{% for opt in item.options %}
|
||||
{{ opt }}
|
||||
{% endfor %}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
flowtable ft {
|
||||
hook ingress priority filter
|
||||
devices = { eth0, eth1 }
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
ct state established,related accept
|
||||
ct state invalid drop
|
||||
|
||||
iif lo accept
|
||||
|
||||
meta mark 0x00000001 accept
|
||||
|
||||
iifname eth0 tcp dport 22 accept
|
||||
iifname eth0.11 tcp dport 22 accept
|
||||
|
||||
iifname eth1 udp dport 51820 accept
|
||||
iifname { eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } udp dport 53 accept
|
||||
iifname { eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } tcp dport 53 accept
|
||||
|
||||
iifname eth0.3 udp dport 67 accept
|
||||
iifname eth1 udp dport 68 accept
|
||||
|
||||
#include "/etc/nftables.d/90-input.nft"
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
|
||||
ct state established,related accept
|
||||
ct state invalid drop
|
||||
|
||||
iifname { eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } oifname eth1 ct state new flow add @ft
|
||||
iifname { eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } oifname eth1 accept
|
||||
|
||||
iifname "zt*" oifname "eth0" accept
|
||||
iifname "eth0" oifname "zt*" accept
|
||||
|
||||
tcp flags syn tcp option maxseg size set rt mtu
|
||||
|
||||
include "/etc/nftables.d/90-forward.nft"
|
||||
}
|
||||
|
||||
chain output {
|
||||
type route hook output priority filter; policy accept;
|
||||
|
||||
#include "/etc/nftables.d/90-output.nft"
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
chain vpn_prerouting_dnat {
|
||||
type nat hook prerouting priority dstnat - 5; policy accept;
|
||||
|
||||
iifname wg0 ip daddr 10.250.251.0/24 counter dnat ip prefix to 10.1.0.0/24
|
||||
iifname wg0 ip daddr 10.250.252.0/24 counter dnat ip prefix to 10.2.0.0/24
|
||||
iifname wg0 ip daddr 10.250.253.0/24 counter dnat ip prefix to 10.10.0.0/24
|
||||
iifname wg0 ip daddr 10.250.254.0/24 counter dnat ip prefix to 10.11.0.0/24
|
||||
iifname wg0 ip daddr 10.250.255.0/24 counter dnat ip prefix to 10.12.0.0/24
|
||||
iifname wg0 ip daddr 10.250.249.0/24 counter dnat ip prefix to 10.13.0.0/24
|
||||
}
|
||||
|
||||
chain vpn_postrouting_snat {
|
||||
type nat hook postrouting priority srcnat; policy accept;
|
||||
|
||||
oifname wg0 ip saddr 10.1.0.0/24 counter snat ip prefix to 10.250.251.0/24
|
||||
oifname wg0 ip saddr 10.2.0.0/24 counter snat ip prefix to 10.250.252.0/24
|
||||
oifname wg0 ip saddr 10.10.0.0/24 counter snat ip prefix to 10.250.253.0/24
|
||||
oifname wg0 ip saddr 10.11.0.0/24 counter snat ip prefix to 10.250.254.0/24
|
||||
oifname wg0 ip saddr 10.12.0.0/24 counter snat ip prefix to 10.250.255.0/24
|
||||
oifname wg0 ip saddr 10.13.0.0/24 counter snat ip prefix to 10.250.249.0/24
|
||||
}
|
||||
|
||||
chain vpn_prerouting_pbr {
|
||||
type filter hook prerouting priority mangle - 10; policy accept;
|
||||
|
||||
iifname wg0 ct state new counter ct mark set 0x000000c7
|
||||
ip daddr 10.0.0.0/8 return
|
||||
iifname != "wg0" ct mark 0x000000c7 counter mark set 0x000000c7
|
||||
}
|
||||
|
||||
chain vpn_output_pbr {
|
||||
type route hook output priority mangle - 10; policy accept;
|
||||
|
||||
ct mark 0x000000c7 counter meta mark set 0x000000c7
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
flush ruleset
|
||||
|
||||
table inet filter {
|
||||
include "/etc/nftables.d/40-sets.nft"
|
||||
include "/etc/nftables.d/90-sets.nft"
|
||||
include "/etc/nftables.d/10-filter.nft"
|
||||
include "/etc/nftables.d/20-vpn.nft"
|
||||
include "/etc/nftables.d/30-proxy.nft"
|
||||
}
|
||||
|
||||
table ip nat {
|
||||
include "/etc/nftables.d/10-nat.nft"
|
||||
}
|
||||
@@ -2,7 +2,6 @@ chain postrouting {
|
||||
type nat hook postrouting priority srcnat; policy accept;
|
||||
oifname eth1 masquerade
|
||||
}
|
||||
|
||||
chain prerouting {
|
||||
type nat hook prerouting priority dstnat; policy accept;
|
||||
include "/etc/nftables.d/90-dstnat.nft"
|
||||
@@ -0,0 +1,34 @@
|
||||
flowtable ft {
|
||||
hook ingress priority filter
|
||||
devices = { eth0, eth1 }
|
||||
}
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
ct state established,related accept
|
||||
ct state invalid drop
|
||||
iif lo accept
|
||||
meta mark 0x00000001 accept
|
||||
iifname br-eth0 tcp dport 22 accept
|
||||
iifname eth0.11 tcp dport 22 accept
|
||||
iifname tun0 tcp dport 22 accept
|
||||
iifname { br-eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } tcp dport 61219 accept
|
||||
iifname { br-eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } udp dport 61219 accept
|
||||
iifname { br-eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } udp dport 53 accept
|
||||
iifname { br-eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } tcp dport 53 accept
|
||||
iifname eth0.3 udp dport 67 accept
|
||||
iifname eth1 udp dport 68 accept
|
||||
include "/etc/nftables.d/90-input.nft"
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
ct state established,related accept
|
||||
ct state invalid drop
|
||||
iifname { br-eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } oifname eth1 ct state new flow add @ft
|
||||
iifname { br-eth0, eth0.2, eth0.3, eth0.4, eth0.10, eth0.11, eth0.12 } oifname eth1 accept
|
||||
tcp flags syn tcp option maxseg size set rt mtu
|
||||
include "/etc/nftables.d/90-forward.nft"
|
||||
}
|
||||
chain output {
|
||||
type route hook output priority filter; policy accept;
|
||||
include "/etc/nftables.d/90-output.nft"
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
chain proxy_prerouting {
|
||||
type filter hook prerouting priority filter - 50; policy accept;
|
||||
|
||||
fib daddr type local accept
|
||||
|
||||
meta mark 0x00000001 iif "lo" meta l4proto { tcp, udp } tproxy ip to :61219 counter accept
|
||||
|
||||
include "/etc/nftables.d/90-proxy-prerouting.nft"
|
||||
}
|
||||
|
||||
chain proxy_output {
|
||||
type route hook output priority mangle; policy accept;
|
||||
|
||||
meta mark != 0 return
|
||||
include "/etc/nftables.d/90-proxy-output.nft"
|
||||
}
|
||||
@@ -4,38 +4,55 @@
|
||||
path: /etc/nftables.d
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: nftables_bootstrap_files | default(false)
|
||||
|
||||
- name: deploy nftables rule
|
||||
- name: bootstrap empty config files
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/nftables.d/{{ item }}"
|
||||
content: ""
|
||||
force: false
|
||||
mode: "0644"
|
||||
loop:
|
||||
- 10-filter.nft
|
||||
- 10-nat.nft
|
||||
- 20-vpn.nft
|
||||
- 30-proxy.nft
|
||||
- 40-sets.nft
|
||||
- 10-sets.nft
|
||||
- 20-sets.nft
|
||||
- 30-nat.nft
|
||||
- 40-filter.nft
|
||||
- 50-proxy.nft
|
||||
- 90-dstnat.nft
|
||||
- 90-forward.nft
|
||||
- 90-input.nft
|
||||
- 90-output.nft
|
||||
- 90-proxy-output.nft
|
||||
- 90-proxy-prerouting.nft
|
||||
when: nftables_bootstrap_files | default(false)
|
||||
|
||||
- name: deploy nftables rules
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/nftables.d/{{ item | basename }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/files/' + inventory_hostname + '/*.nft') }}"
|
||||
notify: restart nftables
|
||||
|
||||
- name: render forward
|
||||
- name: render nftable rules
|
||||
ansible.builtin.template:
|
||||
src: 90-forward.nft.j2
|
||||
dest: /etc/nftables.d/90-forward.nft
|
||||
mode: "0644"
|
||||
notify: restart nftables
|
||||
|
||||
- name: render dstnat
|
||||
ansible.builtin.template:
|
||||
src: 90-dstnat.nft.j2
|
||||
dest: /etc/nftables.d/90-dstnat.nft
|
||||
mode: "0644"
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/nftables.d/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/templates/' + inventory_hostname + '/*.nft.j2') }}"
|
||||
notify: restart nftables
|
||||
|
||||
- name: deploy nftables.conf
|
||||
ansible.builtin.copy:
|
||||
src: nftables.conf
|
||||
dest: /etc/nftables.conf
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
validate: "nft -c -f %s"
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/templates/' + inventory_hostname + '/*.conf.j2') }}"
|
||||
notify: restart nftables
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in nft_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'nft_dst' in client and client.nft_dst is not none %}
|
||||
{% set target_ip = client.container_ip %}
|
||||
{% for client in client.nft_dst %}
|
||||
{% set ports = client.port if (client.port is iterable and client.port is not string) else [client.port] %}
|
||||
{% set protos = client.proto if (client.proto is iterable and client.proto is not string) else [client.proto] %}
|
||||
{% set ifaces = client.iface if (client.iface is iterable and client.iface is not string) else [client.iface] %}
|
||||
{% for proto in protos %}
|
||||
{% for port in ports %}
|
||||
{% for iface in ifaces %}
|
||||
iifname "{{ iface }}" {{ proto }} dport {{ port }} counter dnat ip to {{ target_ip }}:{{ port }} comment "{{ iface }} -> {{ item }}"
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -1,47 +0,0 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in nft_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'nft_to' in client and client.nft_to is not none %}
|
||||
{% set rules = client.nft_to if (client.nft_to is iterable and client.nft_to is not string) else [client.nft_to] %}
|
||||
{% for rule in rules %}
|
||||
{% set rule = rule if rule is mapping else {'to': rule} %}
|
||||
{% set dests = rule.to if (rule.to is iterable and rule.to is not string) else [rule.to] %}
|
||||
{% set protos = rule.proto if (rule.proto is iterable and rule.proto is not string) else [rule.proto | default(none)] %}
|
||||
{% set ports = rule.port if (rule.port is iterable and rule.port is not string) else [rule.port | default(none)] %}
|
||||
{% for dest in dests %}
|
||||
{% if dest.startswith('zone:') %}
|
||||
{% set oif = dest.split(':')[1] %}
|
||||
{% set daddr = none %}
|
||||
{% set dest_name = oif %}
|
||||
{% else %}
|
||||
{% set oif = hostvars[dest].zone_iface %}
|
||||
{% set daddr = hostvars[dest].container_ip %}
|
||||
{% set dest_name = dest %}
|
||||
{% endif %}
|
||||
{% for proto in protos %}
|
||||
{% for port in ports %}
|
||||
iifname "{{ client.zone_iface }}" ip saddr {{ client.container_ip }} oifname "{{ oif }}" {% if daddr %}ip daddr {{ daddr }} {% endif %}{% if proto and port %}{{ proto }} dport {{ port }} {% endif %}counter accept comment "{{ item }} -> {{ dest_name }}"
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for item in nft_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'nft_from' in client and client.nft_from is not none %}
|
||||
{% set rules = client.nft_from if (client.nft_from is iterable and client.nft_from is not string) else [client.nft_from] %}
|
||||
{% for rule in rules %}
|
||||
{% set ifaces = rule.iface if (rule.iface is iterable and rule.iface is not string) else [rule.iface] %}
|
||||
{% set protos = rule.proto if (rule.proto is iterable and rule.proto is not string) else [rule.proto | default(none)] %}
|
||||
{% set ports = rule.port if (rule.port is iterable and rule.port is not string) else [rule.port | default(none)] %}
|
||||
{% for iface in ifaces %}
|
||||
{% for proto in protos %}
|
||||
{% for port in ports %}
|
||||
iifname "{{ iface }}" oifname "{{ client.zone_iface }}" ip daddr {{ client.container_ip }} {% if proto and port %}{{ proto }} dport {{ port }} {% endif %}counter accept comment "{{ iface }} -> {{ item }}"
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/sbin/nft -f
|
||||
flush ruleset
|
||||
table inet filter {
|
||||
chain input {
|
||||
type filter hook input priority filter;
|
||||
policy drop;
|
||||
iif "lo" accept
|
||||
ct state established,related accept
|
||||
ct state invalid drop
|
||||
tcp dport 22 counter accept comment "ssh"
|
||||
tcp dport 80 counter accept comment "http"
|
||||
tcp dport 443 counter accept comment "https"
|
||||
tcp dport 24444 counter accept comment "mcsmanager"
|
||||
tcp dport { 5222, 5223, 5269, 5000, 5270, 5280 } counter accept comment "xmpp"
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority filter;
|
||||
policy drop;
|
||||
ct state established,related accept
|
||||
ip daddr {{ hostvars['coturn']['container_ip'] }} udp dport { 3478, 5349, 49152-65535 } counter accept
|
||||
ip daddr {{ hostvars['coturn']['container_ip'] }} tcp dport { 3478, 5349 } counter accept
|
||||
ip daddr {{ hostvars['mcsmanager']['container_ip'] }} tcp dport 25565 counter accept
|
||||
ip daddr {{ hostvars['steamcmd']['container_ip'] }} udp dport 2456 counter accept
|
||||
ip daddr {{ hostvars['steamcmd']['container_ip'] }} udp dport 2457 counter accept
|
||||
ip daddr {{ hostvars['rbpi4']['container_ip'] }} udp dport 21116 counter accept
|
||||
ip daddr {{ hostvars['rbpi4']['container_ip'] }} tcp dport 21114-21119 counter accept
|
||||
iifname tun0 ip saddr {{ hostvars['workuter']['container_ip'] }} oifname tun0 ip daddr {{ hostvars['xiawrt']['container_ip'] }} tcp dport 22 counter accept
|
||||
iifname tun0 ip saddr {{ hostvars['workuter']['container_ip'] }} oifname tun0 ip daddr {{ hostvars['rbpi4']['container_ip'] }} tcp dport 22 counter accept
|
||||
iifname tun0 ip saddr {{ hostvars['oyacoi-odcm']['container_ip'] }} oifname tun0 ip daddr {{ hostvars['xiawrt']['container_ip'] }} tcp dport 22 counter accept
|
||||
iifname tun0 ip saddr {{ hostvars['oyacoi-odcm']['container_ip'] }} oifname tun0 ip daddr {{ hostvars['rbpi4']['container_ip'] }} tcp dport 22 counter accept
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority filter;
|
||||
policy accept;
|
||||
}
|
||||
}
|
||||
table ip nat {
|
||||
chain prerouting {
|
||||
type nat hook prerouting priority dstnat;
|
||||
policy accept;
|
||||
ip daddr {{ container_ip }} udp dport { 3478, 5349, 49152-65535 } counter dnat to {{ hostvars['coturn']['container_ip'] }}
|
||||
ip daddr {{ container_ip }} tcp dport { 3478, 5349 } counter dnat to {{ hostvars['coturn']['container_ip'] }}
|
||||
ip daddr {{ container_ip }} tcp dport 25565 counter dnat to {{ hostvars['mcsmanager']['container_ip'] }}
|
||||
ip daddr {{ container_ip }} udp dport 2456 counter dnat to {{ hostvars['steamcmd']['container_ip'] }}
|
||||
ip daddr {{ container_ip }} udp dport 2457 counter dnat to {{ hostvars['steamcmd']['container_ip'] }}
|
||||
ip daddr {{ container_ip }} udp dport 21116 counter dnat to {{ hostvars['rbpi4']['container_ip'] }}
|
||||
ip daddr {{ container_ip }} tcp dport 21114-21119 counter dnat to {{ hostvars['rbpi4']['container_ip'] }}
|
||||
}
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat;
|
||||
policy accept;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in nft_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'nft_dst' in client and client.nft_dst is not none %}
|
||||
{% set target_ip = client.container_ip %}
|
||||
{% for client in client.nft_dst %}
|
||||
{% set ports = client.port if (client.port is iterable and client.port is not string) else [client.port] %}
|
||||
{% set protos = client.proto if (client.proto is iterable and client.proto is not string) else [client.proto] %}
|
||||
{% set ifaces = client.iface if (client.iface is iterable and client.iface is not string) else [client.iface] %}
|
||||
{% for proto in protos %}
|
||||
{% for port in ports %}
|
||||
{% for iface in ifaces %}
|
||||
iifname "{{ iface }}" {{ proto }} dport {{ port }} counter dnat ip to {{ target_ip }}:{{ port }} comment "{{ iface }} -> {{ item }}"
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,47 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% for item in nft_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'nft_to' in client and client.nft_to is not none %}
|
||||
{% set rules = client.nft_to if (client.nft_to is iterable and client.nft_to is not string) else [client.nft_to] %}
|
||||
{% for rule in rules %}
|
||||
{% set rule = rule if rule is mapping else {'to': rule} %}
|
||||
{% set dests = rule.to if (rule.to is iterable and rule.to is not string) else [rule.to] %}
|
||||
{% set protos = rule.proto if (rule.proto is iterable and rule.proto is not string) else [rule.proto | default(none)] %}
|
||||
{% set ports = rule.port if (rule.port is iterable and rule.port is not string) else [rule.port | default(none)] %}
|
||||
{% for dest in dests %}
|
||||
{% if dest.startswith('zone:') %}
|
||||
{% set oif = dest.split(':')[1] %}
|
||||
{% set daddr = none %}
|
||||
{% set dest_name = oif %}
|
||||
{% else %}
|
||||
{% set oif = hostvars[dest].zone_iface %}
|
||||
{% set daddr = hostvars[dest].container_ip %}
|
||||
{% set dest_name = dest %}
|
||||
{% endif %}
|
||||
{% for proto in protos %}
|
||||
{% for port in ports %}
|
||||
iifname "{{ client.zone_iface }}" ip saddr {{ client.container_ip }} oifname "{{ oif }}" {% if daddr %}ip daddr {{ daddr }} {% endif %}{% if proto and port %}{{ proto }} dport {{ port }} {% endif %}counter accept comment "{{ item }} -> {{ dest_name }}"
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for item in nft_managed_group | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if 'nft_from' in client and client.nft_from is not none %}
|
||||
{% set rules = client.nft_from if (client.nft_from is iterable and client.nft_from is not string) else [client.nft_from] %}
|
||||
{% for rule in rules %}
|
||||
{% set ifaces = rule.iface if (rule.iface is iterable and rule.iface is not string) else [rule.iface] %}
|
||||
{% set protos = rule.proto if (rule.proto is iterable and rule.proto is not string) else [rule.proto | default(none)] %}
|
||||
{% set ports = rule.port if (rule.port is iterable and rule.port is not string) else [rule.port | default(none)] %}
|
||||
{% for iface in ifaces %}
|
||||
{% for proto in protos %}
|
||||
{% for port in ports %}
|
||||
iifname "{{ iface }}" oifname "{{ client.zone_iface }}" ip daddr {{ client.container_ip }} {% if proto and port %}{{ proto }} dport {{ port }} {% endif %}counter accept comment "{{ iface }} -> {{ item }}"
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% macro set_daddr(rule) %}
|
||||
{%- if rule in (xray_ip_sets | default([])) or rule in (xray_static_sets | default([])) -%}
|
||||
{%- if rule in (xray_ip_sets | default([])) or rule in (xray_static_sets | default([])) -%}
|
||||
{{ rule }}_ip
|
||||
{%- elif rule in (xray_domain_sets | default([])) -%}
|
||||
{%- elif rule in (xray_domain_sets | default([])) -%}
|
||||
{{ rule }}_dom
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
{% for rule in output_rules | default([]) | sort %}
|
||||
ip daddr @{{ set_daddr(rule) }} meta mark set {{ xray_fwmark }} accept
|
||||
{% endfor %}
|
||||
ip daddr @{{ set_daddr(rule) }} meta mark set {{ xray_fwmark }} counter accept comment "router -> tproxy"
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,28 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% macro set_daddr(name) -%}
|
||||
{%- if name == 'all' -%}
|
||||
0.0.0.0/0
|
||||
{%- elif name in (xray_ip_sets | default([])) or name in (xray_static_sets | default([])) -%}
|
||||
@{{ name }}_ip
|
||||
{%- elif name in (xray_domain_sets | default([])) -%}
|
||||
@{{ name }}_dom
|
||||
{%- else -%}
|
||||
invalid_xray_set_{{ name }}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
{% for item in xray_managed_group | default([]) | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if client.xray_policy is defined %}
|
||||
{% set src_ip = client.container_ip %}
|
||||
{% for rule in client.xray_policy %}
|
||||
{% set target_set = rule.bypass | default(rule.proxy) %}
|
||||
{% if rule.bypass is defined %}
|
||||
meta l4proto tcp ip saddr {{ src_ip }} ip daddr {{ set_daddr(target_set) }} counter accept comment "{{ item }} -> accept"
|
||||
meta l4proto udp ip saddr {{ src_ip }} ip daddr {{ set_daddr(target_set) }} counter accept comment "{{ item }} -> accept"
|
||||
{% elif rule.proxy is defined %}
|
||||
meta l4proto tcp ip saddr {{ src_ip }} ip daddr {{ set_daddr(target_set) }} tproxy ip to :{{ xray_tproxy_port }} meta mark set {{ xray_fwmark }} counter accept comment "{{ item }} -> trpoxy"
|
||||
meta l4proto udp ip saddr {{ src_ip }} ip daddr {{ set_daddr(target_set) }} tproxy ip to :{{ xray_tproxy_port }} meta mark set {{ xray_fwmark }} counter accept comment "{{ item }} -> tproxy"
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/sbin/nft -f
|
||||
flush ruleset
|
||||
table inet filter {
|
||||
include "/etc/nftables.d/10-sets.nft"
|
||||
include "/etc/nftables.d/20-sets.nft"
|
||||
include "/etc/nftables.d/40-filter.nft"
|
||||
include "/etc/nftables.d/50-proxy.nft"
|
||||
}
|
||||
table ip nat {
|
||||
include "/etc/nftables.d/30-nat.nft"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# handlers/main.yml
|
||||
---
|
||||
- name: validate nginx config
|
||||
ansible.builtin.command: nginx -t
|
||||
changed_when: false
|
||||
listen: restart nginx
|
||||
|
||||
- name: restart nginx systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: nginx
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
listen: restart nginx
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: deploy nginx config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/nginx/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/templates/' + inventory_hostname + '/*.conf.j2') }}"
|
||||
notify: restart nginx
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
- name: install prerequisites for nginx repository
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- curl
|
||||
- gnupg2
|
||||
- ca-certificates
|
||||
- lsb-release
|
||||
- debian-archive-keyring
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: check if nginx keyring already exists
|
||||
ansible.builtin.stat:
|
||||
path: /usr/share/keyrings/nginx-archive-keyring.gpg
|
||||
register: nginx_keyring
|
||||
|
||||
- name: download nginx gpg key
|
||||
ansible.builtin.get_url:
|
||||
url: https://nginx.org/keys/nginx_signing.key
|
||||
dest: /tmp/nginx_signing.key
|
||||
mode: '0644'
|
||||
when: not nginx_keyring.stat.exists
|
||||
|
||||
- name: dearmor nginx gpg key
|
||||
ansible.builtin.command:
|
||||
cmd: gpg --dearmor --yes -o /usr/share/keyrings/nginx-archive-keyring.gpg /tmp/nginx_signing.key
|
||||
when: not nginx_keyring.stat.exists
|
||||
|
||||
- name: ensure /root/.gnupg exists
|
||||
ansible.builtin.file:
|
||||
path: /root/.gnupg
|
||||
state: directory
|
||||
mode: '0700'
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: verify nginx signing key fingerprint
|
||||
ansible.builtin.command:
|
||||
cmd: gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
|
||||
register: nginx_key_check
|
||||
changed_when: false
|
||||
|
||||
- name: check nginx signing key fingerprint
|
||||
ansible.builtin.fail:
|
||||
msg: "nginx signing key fingerprint mismatch! Got: {{ nginx_key_check.stdout }}"
|
||||
when: "'573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62' not in nginx_key_check.stdout"
|
||||
|
||||
- name: add nginx apt repository
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/sources.list.d/nginx.list
|
||||
content: >-
|
||||
deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg]
|
||||
https://nginx.org/packages/{{ 'mainline/' if (nginx_use_mainline | default(false)) else '' }}debian
|
||||
{{ ansible_facts['distribution_release'] }} nginx
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
register: nginx_repo_file
|
||||
|
||||
- name: set up repository pinning for nginx
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/preferences.d/99nginx
|
||||
content: |
|
||||
Package: *
|
||||
Pin: origin nginx.org
|
||||
Pin: release o=nginx
|
||||
Pin-Priority: 900
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
when: nginx_repo_file.changed
|
||||
|
||||
- name: install nginx
|
||||
ansible.builtin.apt:
|
||||
name: nginx
|
||||
state: present
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: include install
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: include configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
@@ -0,0 +1,37 @@
|
||||
user www-data;
|
||||
worker_processes auto;
|
||||
worker_cpu_affinity auto;
|
||||
pid /run/nginx.pid;
|
||||
error_log /var/log/nginx/error.log;
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
events {
|
||||
worker_connections 768;
|
||||
}
|
||||
stream {
|
||||
upstream haproxy_http {
|
||||
server 127.0.0.1:10080;
|
||||
}
|
||||
upstream haproxy_backend {
|
||||
server 127.0.0.1:10443;
|
||||
}
|
||||
upstream stunnel_tun0_backend {
|
||||
server 127.0.0.1:8443;
|
||||
}
|
||||
upstream stunnel_tap0_backend {
|
||||
server 127.0.0.1:8444;
|
||||
}
|
||||
map $ssl_preread_server_name $backend {
|
||||
liqueur.oyacoi.ru stunnel_tun0_backend;
|
||||
absinthe.oyacoi.ru stunnel_tap0_backend;
|
||||
default haproxy_backend;
|
||||
}
|
||||
server {
|
||||
listen {{ container_ip }}:80;
|
||||
proxy_pass haproxy_http;
|
||||
}
|
||||
server {
|
||||
listen {{ container_ip }}:443;
|
||||
proxy_pass $backend;
|
||||
ssl_preread on;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
iroute 192.168.1.0 255.255.255.0
|
||||
@@ -0,0 +1,7 @@
|
||||
iroute 10.1.0.0 255.255.255.0
|
||||
iroute 10.2.0.0 255.255.255.0
|
||||
iroute 10.3.0.0 255.255.255.0
|
||||
iroute 10.4.0.0 255.255.255.0
|
||||
iroute 10.10.0.0 255.255.255.0
|
||||
iroute 10.11.0.0 255.255.255.0
|
||||
iroute 10.12.0.0 255.255.255.0
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: render openvpn client config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/openvpn/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0600'
|
||||
loop: "{{ query('fileglob', role_path + '/templates/' + inventory_hostname + '/*.conf.j2') }}"
|
||||
register: openvpn_client_configs
|
||||
|
||||
- name: restart openvpn client
|
||||
ansible.builtin.systemd_service:
|
||||
name: "openvpn@{{ item.item | basename | regex_replace('\\.conf\\.j2$', '') }}"
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
loop: "{{ openvpn_client_configs.results }}"
|
||||
when: item.changed
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: deploy ccd files
|
||||
ansible.builtin.copy:
|
||||
src: "{{ role_path }}/files/{{ inventory_hostname }}/ccd/"
|
||||
dest: /etc/openvpn/ccd/
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: render openvpn config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/openvpn/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0600'
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/templates/' + inventory_hostname + '/*.conf.j2') }}"
|
||||
register: openvpn_configs
|
||||
|
||||
- name: restart openvpn
|
||||
ansible.builtin.systemd_service:
|
||||
name: "openvpn@{{ item.item | basename | regex_replace('\\.conf\\.j2$', '') }}"
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
loop: "{{ openvpn_configs.results }}"
|
||||
when: item.changed
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: install openvpn
|
||||
ansible.builtin.apt:
|
||||
name: openvpn
|
||||
state: latest
|
||||
update_cache: true
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: include install
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: include server configuration
|
||||
ansible.builtin.include_tasks: configure-server.yml
|
||||
when: openvpn_role == 'server'
|
||||
|
||||
- name: include client configuration
|
||||
ansible.builtin.include_tasks: configure-client.yml
|
||||
when: openvpn_role == 'client'
|
||||
@@ -0,0 +1,27 @@
|
||||
port 1195
|
||||
proto tcp
|
||||
dev tap0
|
||||
dev-type tap
|
||||
server-bridge nogw
|
||||
client-to-client
|
||||
keepalive 10 60
|
||||
cipher AES-256-GCM
|
||||
auth SHA256
|
||||
persist-key
|
||||
persist-tun
|
||||
status openvpn-tap0-status.log
|
||||
verb 6
|
||||
tun-mtu 1500
|
||||
mssfix 1300
|
||||
<ca>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/ca.crt') }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/issued/server.crt') }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/private/server.key') }}
|
||||
</key>
|
||||
<dh>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/dh.pem') }}
|
||||
</dh>
|
||||
@@ -0,0 +1,44 @@
|
||||
port 1194
|
||||
proto tcp
|
||||
dev tun0
|
||||
server 172.168.0.0 255.255.255.0
|
||||
topology subnet
|
||||
ifconfig-pool-persist ipp.txt
|
||||
route 10.1.0.0 255.255.255.0
|
||||
route 10.2.0.0 255.255.255.0
|
||||
route 10.3.0.0 255.255.255.0
|
||||
route 10.4.0.0 255.255.255.0
|
||||
route 10.10.0.0 255.255.255.0
|
||||
route 10.11.0.0 255.255.255.0
|
||||
route 10.12.0.0 255.255.255.0
|
||||
route 192.168.1.0 255.255.255.0
|
||||
push "route 192.168.1.0 255.255.255.0"
|
||||
push "route 10.1.0.0 255.255.255.0"
|
||||
push "route 10.2.0.0 255.255.255.0"
|
||||
push "route 10.3.0.0 255.255.255.0"
|
||||
push "route 10.4.0.0 255.255.255.0"
|
||||
push "route 10.10.0.0 255.255.255.0"
|
||||
push "route 10.11.0.0 255.255.255.0"
|
||||
push "route 10.12.0.0 255.255.255.0"
|
||||
client-config-dir /etc/openvpn/ccd/liqueur
|
||||
keepalive 10 60
|
||||
cipher AES-256-GCM
|
||||
auth SHA256
|
||||
persist-key
|
||||
persist-tun
|
||||
status openvpn-status.log
|
||||
verb 3
|
||||
tun-mtu 1500
|
||||
mssfix 1300
|
||||
<ca>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/ca.crt') }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/issued/server.crt') }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/private/server.key') }}
|
||||
</key>
|
||||
<dh>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/dh.pem') }}
|
||||
</dh>
|
||||
@@ -0,0 +1,24 @@
|
||||
client
|
||||
dev tap0
|
||||
dev-type tap
|
||||
proto tcp
|
||||
remote 127.0.0.1 1195
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
remote-cert-tls server
|
||||
auth SHA256
|
||||
cipher AES-256-GCM
|
||||
tun-mtu 1500
|
||||
mssfix 1300
|
||||
verb 3
|
||||
<ca>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/ca.crt') }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/issued/ltrefilov.crt') }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tap0/private/ltrefilov.key') }}
|
||||
</key>
|
||||
@@ -0,0 +1,21 @@
|
||||
client
|
||||
dev tun0
|
||||
proto tcp
|
||||
remote 127.0.0.1 1194
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
remote-cert-tls server
|
||||
auth SHA256
|
||||
cipher AES-256-GCM
|
||||
verb 3
|
||||
<ca>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/ca.crt') }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/issued/mur89.crt') }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ lookup('file', '/etc/easy-rsa/pki/tun0/private/mur89.key') }}
|
||||
</key>
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: restart sshd
|
||||
ansible.builtin.service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: disable password authentication
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PasswordAuthentication\s'
|
||||
line: 'PasswordAuthentication no'
|
||||
validate: '/usr/sbin/sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
|
||||
- name: enable root authentication
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitRootLogin\s'
|
||||
line: 'PermitRootLogin prohibit-password'
|
||||
validate: '/usr/sbin/sshd -t -f %s'
|
||||
notify: restart sshd
|
||||
@@ -1,3 +1,3 @@
|
||||
---
|
||||
- name: include xray-core configurure
|
||||
- name: include configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
@@ -0,0 +1,9 @@
|
||||
setuid = stunnel4
|
||||
setgid = stunnel4
|
||||
pid = /var/run/stunnel4/absinthe.pid
|
||||
output = /var/log/stunnel4/absinthe.log
|
||||
[openvpn]
|
||||
cert = /etc/letsencrypt/live/absinthe.oyacoi.ru/fullchain.pem
|
||||
key = /etc/letsencrypt/live/absinthe.oyacoi.ru/privkey.pem
|
||||
accept = 127.0.0.1:8444
|
||||
connect = 127.0.0.1:1195
|
||||
@@ -0,0 +1,9 @@
|
||||
setuid = stunnel4
|
||||
setgid = stunnel4
|
||||
pid = /var/run/stunnel4/liqueur.pid
|
||||
output = /var/log/stunnel4/liqueur.log
|
||||
[openvpn]
|
||||
cert = /etc/letsencrypt/live/liqueur.oyacoi.ru/fullchain.pem
|
||||
key = /etc/letsencrypt/live/liqueur.oyacoi.ru/privkey.pem
|
||||
accept = 127.0.0.1:8443
|
||||
connect = 127.0.0.1:1194
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: restart stunnel4
|
||||
ansible.builtin.service:
|
||||
name: stunnel4
|
||||
state: restarted
|
||||
listen: restart stunnel4
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
- name: ensure /var/run/stunnel exists
|
||||
ansible.builtin.file:
|
||||
path: /var/run/stunnel
|
||||
owner: stunnel4
|
||||
group: stunnel4
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: ensure /var/log/stunnel exists
|
||||
ansible.builtin.file:
|
||||
path: /var/log/stunnel
|
||||
state: directory
|
||||
owner: stunnel4
|
||||
group: stunnel4
|
||||
mode: "0755"
|
||||
|
||||
- name: deploy stunnel config
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/stunnel/{{ item | basename }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
loop: "{{ query('fileglob', role_path + '/files/' + inventory_hostname + '/*.conf') }}"
|
||||
notify: restart stunnel4
|
||||
|
||||
- name: render stunnel config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/etc/stunnel/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
loop: "{{ query('fileglob', role_path + '/templates/' + inventory_hostname + '/*.conf.j2') }}"
|
||||
notify: restart stunnel4
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: install stunnel4
|
||||
ansible.builtin.apt:
|
||||
name: stunnel4
|
||||
state: latest
|
||||
update_cache: true
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: include install
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: include configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
@@ -0,0 +1,9 @@
|
||||
setuid = stunnel4
|
||||
setgid = stunnel4
|
||||
pid = /var/run/stunnel/absinthe.pid
|
||||
output = /var/log/stunnel/absinthe.log
|
||||
client = yes
|
||||
[openvpn]
|
||||
sni = absinthe.oyacoi.ru
|
||||
accept = 127.0.0.1:1195
|
||||
connect = {{ hostvars['liqueur'].container_ip }}:443
|
||||
@@ -0,0 +1,9 @@
|
||||
setuid = stunnel4
|
||||
setgid = stunnel4
|
||||
pid = /var/run/stunnel/liqueur.pid
|
||||
output = /var/log/stunnel/liqueur.log
|
||||
client = yes
|
||||
[openvpn]
|
||||
sni = liqueur.oyacoi.ru
|
||||
accept = 127.0.0.1:1194
|
||||
connect = {{ hostvars['liqueur'].container_ip }}:443
|
||||
@@ -0,0 +1,2 @@
|
||||
net.ipv4.ip_forward = 1
|
||||
net.ipv4.conf.all.route_localnet = 1
|
||||
@@ -0,0 +1,6 @@
|
||||
net.ipv4.ip_forward = 1
|
||||
net.ipv4.conf.lo.rp_filter = 0
|
||||
net.ipv4.conf.all.rp_filter = 0
|
||||
net.bridge.bridge-nf-call-iptables = 0
|
||||
net.bridge.bridge-nf-call-ip6tables = 0
|
||||
net.bridge.bridge-nf-call-arptables = 0
|
||||
@@ -1,7 +1,7 @@
|
||||
- name: deploy sysctl config
|
||||
ansible.builtin.template:
|
||||
src: sysctl.conf.j2
|
||||
dest: "/etc/sysctl.d/99-custom.conf"
|
||||
ansible.builtin.copy:
|
||||
src: "{{ inventory_hostname }}/"
|
||||
dest: "/etc/sysctl.d/"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{% for key, value in sysctl.items() %}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor %}
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: restart wg0 systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: wg-quick@wg0
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
- name: ensure /etc/wireguard exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/wireguard
|
||||
state: directory
|
||||
mode: "0700"
|
||||
|
||||
- name: deploy wireguard config
|
||||
ansible.builtin.template:
|
||||
src: "wg0.conf.j2"
|
||||
dest: "/etc/wireguard/wg0.conf"
|
||||
mode: "0644"
|
||||
register: wg0_conf
|
||||
|
||||
- name: restart wg0 systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: wg-quick@wg0
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
when: wg0_conf.changed
|
||||
@@ -1,17 +0,0 @@
|
||||
[Interface]
|
||||
PrivateKey = {{ wg_private_key }}
|
||||
Address = {{ wg_address }}
|
||||
Table = off
|
||||
PostUp = ip route add 10.250.250.0/24 dev wg0 2>/dev/null || true
|
||||
PostUp = ip rule add fwmark 0xc7 lookup 199 2>/dev/null || true
|
||||
PostUp = ip route add default dev wg0 table 199 2>/dev/null || true
|
||||
PreDown = ip route del default dev wg0 table 199 2>/dev/null || true
|
||||
PreDown = ip rule del fwmark 0xc7 lookup 199 2>/dev/null || true
|
||||
PreDown = ip route del 10.250.250.0/24 dev wg0 2>/dev/null || true
|
||||
|
||||
[Peer]
|
||||
PublicKey = {{ wg_public_key }}
|
||||
PresharedKey = {{ wg_presharedkey }}
|
||||
Endpoint = {{ wg_endpoint_address }}:{{ wg_endpoint_port }}
|
||||
PersistentKeepalive = 25
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
- name: ensure /opt/xray-core/config exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/xray-core/config
|
||||
state: directory
|
||||
mode: 0755
|
||||
|
||||
- name: ensure /var/log/xray-core exists
|
||||
ansible.builtin.file:
|
||||
path: /var/log/xray-core
|
||||
state: directory
|
||||
mode: 0755
|
||||
|
||||
- name: deploy static xray-core config
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/opt/xray-core/config/{{ item }}"
|
||||
mode: 0744
|
||||
loop:
|
||||
- dns.jsonc
|
||||
- inbounds.jsonc
|
||||
- log.jsonc
|
||||
- policy.jsonc
|
||||
register: xray_core_static_config
|
||||
|
||||
- name: deploy dynamic xray-core config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}.j2"
|
||||
dest: "/opt/xray-core/config/{{ item }}"
|
||||
mode: 0744
|
||||
loop:
|
||||
- observatory.jsonc
|
||||
- outbounds.jsonc
|
||||
- routing.jsonc
|
||||
register: xray_core_dynamic_config
|
||||
|
||||
- name: restart xray-core systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: xray-core
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
when: xray_core_static_config.changed or xray_core_dynamic_config.changed
|
||||
+2
-2
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "tproxy-in",
|
||||
"port": 61219,
|
||||
"listen": "0.0.0.0",
|
||||
"protocol": "dokodemo-door",
|
||||
@@ -12,8 +13,7 @@
|
||||
"sockopt": {
|
||||
"tproxy": "tproxy"
|
||||
}
|
||||
},
|
||||
"tag": "tproxy"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "socks-in",
|
||||
@@ -6,12 +6,16 @@ Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
User=xray-core
|
||||
Group=xray-core
|
||||
WorkingDirectory=/opt/xray-core
|
||||
ExecStart=/opt/xray-core/xray -confdir /opt/xray-core/config
|
||||
Restart=on-failure
|
||||
RestartSec=3s
|
||||
LimitNOFILE=65535
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
|
||||
NoNewPrivileges=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: validate xray-core config
|
||||
ansible.builtin.command: su -s /bin/sh xray-core -c "/opt/xray-core/xray run -test -confdir /opt/xray-core/config"
|
||||
changed_when: false
|
||||
listen: restart xray-core
|
||||
|
||||
- name: restart xray-core systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: xray-core
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
listen: restart xray-core
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
- name: ensure /opt/xray-core/config exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/xray-core/config
|
||||
state: directory
|
||||
owner: xray-core
|
||||
group: xray-core
|
||||
mode: "0755"
|
||||
|
||||
- name: ensure /var/log/xray-core exists
|
||||
ansible.builtin.file:
|
||||
path: /var/log/xray-core
|
||||
state: directory
|
||||
owner: xray-core
|
||||
group: xray-core
|
||||
mode: "0755"
|
||||
|
||||
- name: deploy xray-core static config
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item }}"
|
||||
dest: "/opt/xray-core/config/{{ item | basename }}"
|
||||
owner: xray-core
|
||||
group: xray-core
|
||||
mode: "0644"
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/files/' + inventory_hostname + '/*.jsonc') }}"
|
||||
notify: restart xray-core
|
||||
|
||||
- name: render xray-core dynamic config
|
||||
ansible.builtin.template:
|
||||
src: "{{ item }}"
|
||||
dest: "/opt/xray-core/config/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
owner: xray-core
|
||||
group: xray-core
|
||||
mode: "0644"
|
||||
loop: "{{ query('ansible.builtin.fileglob', role_path + '/templates/' + inventory_hostname + '/*.jsonc.j2') }}"
|
||||
notify: restart xray-core
|
||||
@@ -10,6 +10,7 @@
|
||||
return_content: yes
|
||||
register: xray_release
|
||||
run_once: true
|
||||
check_mode: false
|
||||
|
||||
- name: set current xray-core version
|
||||
ansible.builtin.set_fact:
|
||||
@@ -25,6 +26,8 @@
|
||||
- name: ensure xray-core directory exists
|
||||
ansible.builtin.file:
|
||||
path: /opt/xray-core
|
||||
owner: xray-core
|
||||
group: xray-core
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
@@ -33,10 +36,12 @@
|
||||
src: "{{ xray_asset_url }}"
|
||||
dest: /opt/xray-core
|
||||
remote_src: yes
|
||||
owner: xray-core
|
||||
group: xray-core
|
||||
when: xray_version not in (xray_current_version.stdout | default(''))
|
||||
|
||||
- name: deploy xray-core systemd service unit
|
||||
ansible.builtin.copy:
|
||||
src: xray-core.service
|
||||
dest: /etc/systemd/system/xray-core.service
|
||||
mode: 755
|
||||
mode: 0644
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
- name: include xray-core user
|
||||
ansible.builtin.include_tasks: user.yml
|
||||
|
||||
- name: include xray-core install
|
||||
ansible.builtin.include_tasks: install.yml
|
||||
|
||||
- name: include xray-core configure
|
||||
ansible.builtin.include_tasks: configure.yml
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: create xray-core system group
|
||||
ansible.builtin.group:
|
||||
name: xray-core
|
||||
system: true
|
||||
state: present
|
||||
|
||||
- name: create xray-core system user
|
||||
ansible.builtin.user:
|
||||
name: xray-core
|
||||
group: xray-core
|
||||
system: true
|
||||
shell: /usr/sbin/nologin
|
||||
home: /opt/xray-core
|
||||
create_home: false
|
||||
state: present
|
||||
-10
@@ -33,9 +33,6 @@
|
||||
"h3"
|
||||
],
|
||||
"fingerprint": "firefox"
|
||||
},
|
||||
"sockopt": {
|
||||
"mark": 255
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -45,13 +42,6 @@
|
||||
"protocol": "freedom",
|
||||
"settings": {
|
||||
"domainStrategy": "UseIPv4"
|
||||
},
|
||||
"streamSettings": {
|
||||
"sockopt": {
|
||||
"mark": 255,
|
||||
"interface": "eth1",
|
||||
"tcpFastOpen": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": [
|
||||
"tproxy",
|
||||
"tproxy-in",
|
||||
"socks-in"
|
||||
],
|
||||
"balancerTag": "{{ 'balancer-vless' if xray_outbounds | length > 1 else 'vless-' ~ xray_outbounds[0].tag }}"
|
||||
@@ -17,35 +17,3 @@
|
||||
name: xray-lists.service
|
||||
state: started
|
||||
when: xray_lists_config.changed
|
||||
|
||||
- name: bootstrap empty config files
|
||||
ansible.builtin.copy:
|
||||
dest: "/etc/nftables.d/{{ item }}"
|
||||
content: ""
|
||||
force: false
|
||||
mode: "0644"
|
||||
loop:
|
||||
- 90-sets.nft
|
||||
- 90-proxy-prerouting.nft
|
||||
- 90-proxy-output.nft
|
||||
|
||||
- name: render nft sets
|
||||
ansible.builtin.template:
|
||||
src: 90-sets.nft.j2
|
||||
dest: /etc/nftables.d/90-sets.nft
|
||||
mode: "0644"
|
||||
notify: reload nftables
|
||||
|
||||
- name: render proxy prerouting
|
||||
ansible.builtin.template:
|
||||
src: 90-proxy-prerouting.nft.j2
|
||||
dest: /etc/nftables.d/90-proxy-prerouting.nft
|
||||
mode: "0644"
|
||||
notify: reload nftables
|
||||
|
||||
- name: render proxy output
|
||||
ansible.builtin.template:
|
||||
src: 90-proxy-output.nft.j2
|
||||
dest: /etc/nftables.d/90-proxy-output.nft
|
||||
mode: "0644"
|
||||
notify: reload nftables
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#jinja2: trim_blocks: True, lstrip_blocks: True
|
||||
{% macro set_daddr(name) %}
|
||||
{%- if name == 'all' %}
|
||||
0.0.0.0/0
|
||||
{%- elif name in (xray_ip_sets | default([])) or name in (xray_static_sets | default([])) %}
|
||||
@{{ name }}_ip
|
||||
{%- elif name in (xray_domain_sets | default([])) %}
|
||||
@{{ name }}_dom
|
||||
{%- else %}
|
||||
invalid_xray_set_{{ name }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
{% for item in xray_managed_group | default([]) | sort %}
|
||||
{% set client = hostvars[item] %}
|
||||
{% if client.xray_policy is defined %}
|
||||
{% set src_ip = client.container_ip %}
|
||||
{% for rule in client.xray_policy %}
|
||||
{% set target_set = rule.bypass | default(rule.proxy) %}
|
||||
{% if rule.bypass is defined %}
|
||||
meta l4proto { tcp, udp } ip saddr {{ src_ip }} ip daddr {{ set_daddr(target_set) }} accept
|
||||
{% elif rule.proxy is defined %}
|
||||
meta l4proto { tcp, udp } ip saddr {{ src_ip }} ip daddr {{ set_daddr(target_set) }} tproxy ip to :{{ xray_tproxy_port }} meta mark set {{ xray_fwmark }} accept
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -3,49 +3,49 @@ global:
|
||||
cache_dir: {{ xray_lists_global.cache_dir }}
|
||||
output_dir: {{ xray_lists_global.output_dir }}
|
||||
dnsmasq_output: {{ xray_lists_global.dnsmasq_output }}
|
||||
{% if xray_lists_global.proxy is defined %}
|
||||
{% if xray_lists_global.proxy is defined %}
|
||||
proxy: "{{ xray_lists_global.proxy }}"
|
||||
{% endif %}
|
||||
{% if proxy_user is defined %}
|
||||
{% endif %}
|
||||
{% if proxy_user is defined %}
|
||||
proxy_user: "{{ proxy_user }}"
|
||||
proxy_pass: "{{ proxy_pass }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
http_timeout: {{ xray_lists_global.http_timeout | default(20) }}
|
||||
ip_sets:
|
||||
{% for id, item in xray_ip_sets.items() %}
|
||||
{% for id, item in xray_ip_sets.items() %}
|
||||
- id: {{ id }}
|
||||
output: {{ id }}_ip.elements.nft
|
||||
{% if item.static is defined %}
|
||||
{% if item.static is defined %}
|
||||
static:
|
||||
{% for s in item.static %}
|
||||
{% for s in item.static %}
|
||||
- {{ s }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if item.urls is defined %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if item.urls is defined %}
|
||||
urls:
|
||||
{% for u in item.urls %}
|
||||
{% for u in item.urls %}
|
||||
- {{ u }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
domain_sets:
|
||||
{% for id, item in xray_domain_sets.items() %}
|
||||
{% for id, item in xray_domain_sets.items() %}
|
||||
- id: {{ id }}
|
||||
dnsmasq_target: "4#inet#filter#{{ id }}_dom"
|
||||
{% if item.static is defined %}
|
||||
{% if item.static is defined %}
|
||||
static:
|
||||
{% for s in item.static %}
|
||||
{% for s in item.static %}
|
||||
- {{ s }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if item.urls is defined %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if item.urls is defined %}
|
||||
urls:
|
||||
{% for u in item.urls %}
|
||||
{% for u in item.urls %}
|
||||
- {{ u }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
output_rules:
|
||||
{% for rule in output_rules %}
|
||||
{% for rule in output_rules %}
|
||||
- {{ rule }}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
- name: reload nftables
|
||||
ansible.builtin.command: nft -f /etc/nftables.conf
|
||||
|
||||
- name: restart zerotier-one systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: zerotier-one
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
- name: create networks.d directory
|
||||
ansible.builtin.file:
|
||||
path: /var/lib/zerotier-one/networks.d
|
||||
state: directory
|
||||
mode: 0700
|
||||
owner: zerotier-one
|
||||
group: zerotier-one
|
||||
|
||||
- name: check if zerotier-one network config exists
|
||||
ansible.builtin.stat:
|
||||
path: "/var/lib/zerotier-one/networks.d/{{ zerotier_network_id }}.conf"
|
||||
register: zerotier_network_stat
|
||||
|
||||
- name: create zerotier-one network config
|
||||
ansible.builtin.file:
|
||||
path: "/var/lib/zerotier-one/networks.d/{{ zerotier_network_id }}.conf"
|
||||
state: touch
|
||||
mode: "0600"
|
||||
owner: zerotier-one
|
||||
group: zerotier-one
|
||||
when: not zerotier_network_stat.stat.exists
|
||||
register: zerotier_network
|
||||
|
||||
- name: restart zerotier-one systemd service unit
|
||||
ansible.builtin.systemd_service:
|
||||
name: zerotier-one
|
||||
daemon_reload: true
|
||||
state: restarted
|
||||
enabled: true
|
||||
when: zerotier_network.changed
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
- name: add zerotier repository
|
||||
ansible.builtin.deb822_repository:
|
||||
name: zerotier
|
||||
types: deb
|
||||
uris: "http://download.zerotier.com/debian/trixie"
|
||||
suites: "trixie"
|
||||
components: main
|
||||
signed_by: "https://download.zerotier.com/contact%40zerotier.com.gpg"
|
||||
state: present
|
||||
|
||||
- name: install zerotier-one
|
||||
ansible.builtin.apt:
|
||||
name: zerotier-one
|
||||
state: latest
|
||||
update_cache: true
|
||||
@@ -1,17 +0,0 @@
|
||||
[Interface]
|
||||
PrivateKey = {{ wg_private_key }}
|
||||
Address = {{ wg_address }}
|
||||
Table = off
|
||||
PostUp = ip route add 10.250.250.0/24 dev wg0 2>/dev/null || true
|
||||
PostUp = ip rule add fwmark 0xc7 lookup 199 2>/dev/null || true
|
||||
PostUp = ip route add default dev wg0 table 199 2>/dev/null || true
|
||||
PreDown = ip route del default dev wg0 table 199 2>/dev/null || true
|
||||
PreDown = ip rule del fwmark 0xc7 lookup 199 2>/dev/null || true
|
||||
PreDown = ip route del 10.250.250.0/24 dev wg0 2>/dev/null || true
|
||||
|
||||
[Peer]
|
||||
PublicKey = {{ wg_public_key }}
|
||||
PresharedKey = {{ wg_presharedkey }}
|
||||
Endpoint = {{ wg_endpoint_address }}:{{ wg_endpoint_port }}
|
||||
PersistentKeepalive = 25
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Reference in New Issue
Block a user