summaryrefslogtreecommitdiff
path: root/roles/base
diff options
context:
space:
mode:
Diffstat (limited to 'roles/base')
-rw-r--r--roles/base/handlers/main.yaml11
-rw-r--r--roles/base/tasks/add_pubkeys.yaml9
-rw-r--r--roles/base/tasks/base_setup.yaml58
-rw-r--r--roles/base/tasks/main.yaml12
-rw-r--r--roles/base/tasks/pre_execution_checks.yaml11
-rw-r--r--roles/base/tasks/setup_user_expiration.yaml19
-rw-r--r--roles/base/templates/newsyslog.conf.j231
-rw-r--r--roles/base/templates/syslog.conf.j221
-rw-r--r--roles/base/templates/user_expiration_control.py.j299
9 files changed, 271 insertions, 0 deletions
diff --git a/roles/base/handlers/main.yaml b/roles/base/handlers/main.yaml
new file mode 100644
index 00000000..f229852c
--- /dev/null
+++ b/roles/base/handlers/main.yaml
@@ -0,0 +1,11 @@
+---
+- name: restart_notification
+ ansible.builtin.debug:
+ msg: "Restart your box for sysctl.conf and syslog.conf to take effect"
+
+- name: syslogd_restart
+ ansible.builtin.service:
+ name: syslogd
+ state: restarted
+ enabled: true
+
diff --git a/roles/base/tasks/add_pubkeys.yaml b/roles/base/tasks/add_pubkeys.yaml
new file mode 100644
index 00000000..9f0e7c59
--- /dev/null
+++ b/roles/base/tasks/add_pubkeys.yaml
@@ -0,0 +1,9 @@
+---
+- name: "add pubkeys to root user"
+ ansible.builtin.lineinfile:
+ path: /root/.ssh/authorized_keys
+ create: true
+ line: "{{ item | trim }}"
+ search_string: "{{ (item | trim | split(' '))[2:-1]|join(' ') }}"
+ when: "root_keys is defined"
+ loop: "{{ root_keys }}"
diff --git a/roles/base/tasks/base_setup.yaml b/roles/base/tasks/base_setup.yaml
new file mode 100644
index 00000000..f1ed062a
--- /dev/null
+++ b/roles/base/tasks/base_setup.yaml
@@ -0,0 +1,58 @@
+---
+- name: "Create vpns user"
+ ansible.builtin.user:
+ name: _vpn
+ create_home: no
+ comment: Project VPN user
+ state: present
+ shell: /sbin/nologin
+ notify: restart_notification
+
+- name: "Create root directory of vpn services"
+ ansible.builtin.file:
+ path: /var/reactance/
+ state: directory
+ owner: _vpn
+ group: _vpn
+ mode: 0755
+
+- name: "templating out ip forwarding rules in sysctl.conf"
+ ansible.builtin.blockinfile:
+ path: /etc/sysctl.conf
+ create: true
+ backup: true
+ marker: "### REACTANCE - IP Forwarding - {mark} ###"
+ insertafter: "EOF"
+ block: |
+ net.inet.ip.forwarding=1
+ net.inet6.ip6.forwarding=1
+
+- name: "templating out sysctl.conf"
+ ansible.builtin.template:
+ src: "{{ item.src }}"
+ dest: "{{ item.dest }}"
+ mode: '0644'
+ notify: syslogd_restart
+ loop:
+ - src: syslog.conf.j2
+ dest: /etc/syslog.conf
+ - src: newsyslog.conf.j2
+ dest: /etc/newsyslog.conf
+
+
+# openbsd_pkg cant be run parallely otherwise there could be package locks and pipeline would fail
+- name: "install necessary utils"
+ community.general.openbsd_pkg:
+ name:
+ - unzip--
+ - curl--
+ - rsync--
+ - jq--
+ state: present
+ when: inventory_hostname in (groups['vless']|default([]) + groups['vmess']|default([]) + groups['trojan']|default([]) + groups['all_vpns']|default([]))
+
+- name: "tune unbound performance"
+ community.general.openbsd_pkg:
+ name: ripgrep
+ state: present
+ when: not disable_dns|default(False)
diff --git a/roles/base/tasks/main.yaml b/roles/base/tasks/main.yaml
new file mode 100644
index 00000000..5ab9bf45
--- /dev/null
+++ b/roles/base/tasks/main.yaml
@@ -0,0 +1,12 @@
+---
+- name: "add root pubkeys"
+ ansible.builtin.include_tasks: add_pubkeys.yaml
+
+- name: "run pre execution checks"
+ ansible.builtin.include_tasks: pre_execution_checks.yaml
+
+- name: "run base setup"
+ ansible.builtin.include_tasks: base_setup.yaml
+
+- name: "template out user expiration script and cronjob"
+ ansible.builtin.include_tasks: setup_user_expiration.yaml
diff --git a/roles/base/tasks/pre_execution_checks.yaml b/roles/base/tasks/pre_execution_checks.yaml
new file mode 100644
index 00000000..f6a969a7
--- /dev/null
+++ b/roles/base/tasks/pre_execution_checks.yaml
@@ -0,0 +1,11 @@
+---
+- name: "pre execution test : check os"
+ ansible.builtin.fail:
+ msg: "Reactance can only be ran on OpenBSD"
+ when: ansible_facts["os_family"]|lower != "openbsd"
+
+- name: "pre execution test : looking for invalid usernames"
+ ansible.builtin.fail:
+ msg: "Username cannot be 'server' or 'ca'"
+ when: item.user in ["server", "ca"]
+ loop: "{{ all_users|default([]) + ocserv_users|default([]) + vless_users|default([]) + vmess_users|default([]) + trojan_users|default([]) + sshvpn_users|default([]) + hysteria_users|default([]) }}"
diff --git a/roles/base/tasks/setup_user_expiration.yaml b/roles/base/tasks/setup_user_expiration.yaml
new file mode 100644
index 00000000..977977f9
--- /dev/null
+++ b/roles/base/tasks/setup_user_expiration.yaml
@@ -0,0 +1,19 @@
+---
+- name: "Template out user expiration script"
+ ansible.builtin.template:
+ src: user_expiration_control.py.j2
+ dest: /root/.user_expiration_control.py
+ mode: "0400"
+ owner: root
+ group: nogroup
+
+- name: "write user expiration information to file"
+ user_expiration:
+ users: "{{ all_users|default([]) + ocserv_users|default([]) + vless_users|default([]) + vmess_users|default([]) + trojan_users|default([]) + sshvpn_users|default([]) + hysteria_users|default([]) }}"
+
+- name: "setup daily user expiration cronjob"
+ ansible.builtin.cron:
+ name: "daily run user expiration script"
+ user: root
+ job: "python3 /root/.user_expiration_control.py"
+ special_time: daily
diff --git a/roles/base/templates/newsyslog.conf.j2 b/roles/base/templates/newsyslog.conf.j2
new file mode 100644
index 00000000..a8f348d6
--- /dev/null
+++ b/roles/base/templates/newsyslog.conf.j2
@@ -0,0 +1,31 @@
+# $OpenBSD: newsyslog.conf - fsa generated
+#
+# NOTE: SIGHUP has to be sent to syslogd for services whose logs are being written by syslogd
+#
+# logfile_name owner:group mode count size when flags
+/var/cron/log root:wheel 600 3 10 * Z
+/var/log/authlog root:wheel 640 7 * 168 Z
+/var/log/daemon 640 5 300 * Z
+/var/log/lpd-errs 640 7 10 * Z
+/var/log/maillog 640 7 * 24 Z
+/var/log/messages 644 5 300 * Z
+/var/log/secure 600 7 * 168 Z
+/var/log/wtmp 644 7 * $M1D4 B ""
+/var/log/xferlog 640 7 250 * Z
+/var/log/pflog 600 3 250 * ZB "pkill -HUP -u root -U root -t - -x pflogd"
+/var/www/logs/access.log 644 4 * $W0 Z "pkill -USR1 -u root -U root -x httpd"
+/var/www/logs/error.log 644 7 250 * Z "pkill -USR1 -u root -U root -x httpd"
+{# for services whose logs are written by syslogd, we need to restart syslogd instead #}
+{% if inventory_hostname in (groups['xray']|default([])) + (groups['all_vpns']|default([])) %}
+/var/reactance/xray/logs/xray-access.log 640 4 512 * Z "pkill -HUP -u root -U root -x xray"
+/var/reactance/xray/logs/xray-error.log 640 4 512 * Z "pkill -HUP -u root -U root -x xray"
+{% endif %}
+{% if not disable_dns|default(true) %}
+/var/log/unbound.log 600 5 * $W0 Z "pkill -HUP -u root -U root -x syslogd"
+{% endif %}
+{% if inventory_hostname in (groups['ocserv']|default([])) + (groups['all_vpns']|default([])) %}
+/var/log/ocserv.log 600 5 128000 * Z "pkill -HUP -u root -U root -x syslogd"
+{% endif %}
+{% if inventory_hostname in (groups['trojan']|default([])) + (groups['vless']|default([])) + (groups['vmess']|default([])) + (groups['all_vpns']|default([])) %}
+/var/log/relayd.log 600 5 512 * Z "pkill -HUP -u root -U root -x syslogd"
+{% endif %}
diff --git a/roles/base/templates/syslog.conf.j2 b/roles/base/templates/syslog.conf.j2
new file mode 100644
index 00000000..261b6d88
--- /dev/null
+++ b/roles/base/templates/syslog.conf.j2
@@ -0,0 +1,21 @@
+# $OpenBSD: syslog.conf,v 1.20 2016/12/27 13:38:14 jca Exp $
+
+*.notice;auth,authpriv,cron,ftp,kern,lpr,mail,user.none /var/log/messages
+kern.debug;syslog,user.info /var/log/messages
+auth.info /var/log/authlog
+authpriv.debug /var/log/secure
+cron.info /var/cron/log
+{% if inventory_hostname in (groups['ocserv']|default([])) + (groups['all_vpns']|default([])) %}
+!!ocserv
+daemon.* /var/log/ocserv.log
+!*
+{% endif %}
+{% if inventory_hostname in (groups['hysteria']|default([])) + (groups['all_vpns']|default([])) %}
+!!hysteria
+daemon.* /var/log/hysteria.log
+!*
+{% endif %}
+daemon.info /var/log/daemon
+ftp.info /var/log/xferlog
+lpr.debug /var/log/lpd-errs
+mail.info /var/log/maillog
diff --git a/roles/base/templates/user_expiration_control.py.j2 b/roles/base/templates/user_expiration_control.py.j2
new file mode 100644
index 00000000..36551617
--- /dev/null
+++ b/roles/base/templates/user_expiration_control.py.j2
@@ -0,0 +1,99 @@
+#!/usr/local/bin/python3
+
+import json, os, subprocess, shutil
+from datetime import datetime
+
+EXPIRE_USER_JSON_PATH = "/var/reactance/.user_expiration.json"
+EXPIRE_WEB_JSON_PATH = "/var/reactance/.web_expiration.json"
+OCSERV_CONFIG_PATH = "/var/reactance/ocserv/etc/ocserv.passwd"
+HYSTERIA_CONFIG_FILE = "/var/reactance/hysteria/etc/config.json"
+XRAY_CONFIG_PATH = "/var/reactance/xray/etc/config.json"
+SSH_ROOT = "/var/reactance/sshvpn/.ssh"
+AUTHORIZED_KEYS = os.path.join(SSH_ROOT, "authorized_keys")
+
+def ocserv_get_users():
+ ocserv_config_dict = {}
+ if os.path.isfile(OCSERV_CONFIG_PATH):
+ with open(OCSERV_CONFIG_PATH, "r") as f:
+ ocserv_content = f.read()
+ ocserv_config_dict = dict(map(lambda x: x.split(':*:'), list(filter(lambda x: x != '', ocserv_content.split("\n")))))
+ return ocserv_config_dict
+
+def xray_get_users():
+ with open(XRAY_CONFIG_PATH, "r") as f:
+ xray_config_dict = json.loads(f.read())
+ return xray_config_dict
+
+def hysteria_get_users():
+ with open(HYSTERIA_CONFIG_FILE, "r") as f:
+ hysteria_config_dict = json.loads(f.read())
+ return hysteria_config_dict
+
+def sshvpn_get_users():
+ previous_users = [".".join(i.split('.')[:-1]) for i in os.listdir(SSH_ROOT) if i.endswith(".pub")]
+ return previous_users
+
+def ocserv_user_purge(users_to_remove):
+ for user in users_to_remove:
+ subprocess.run(f"ocpasswd -d {user} -c {OCSERV_CONFIG_PATH}", shell=True)
+
+def xray_user_purge(users_to_remove):
+ xray_config_dict = xray_get_users()
+ for i, inbound in enumerate(xray_config_dict['inbounds']):
+ previous_users_list = inbound['settings']['clients']
+ new_users_list = previous_users_list.copy()
+ for user in previous_users_list:
+ if user['email'] in users_to_remove:
+ new_users_list.remove(user)
+ xray_config_dict['inbounds'][i]['settings']['clients'] = new_users_list
+ with open(XRAY_CONFIG_PATH, "w") as f:
+ f.write(json.dumps(xray_config_dict, indent=1))
+
+def hysteria_user_purge(users_to_remove):
+ hysteria_config_dict = hysteria_get_users()
+ previous_users_dict = hysteria_config_dict["auth"]["userpass"]
+ new_users_dict = {}
+ for user in previous_users_dict.keys():
+ if user not in users_to_remove:
+ new_users_dict[user] = previous_users_dict[user]
+ hysteria_config_dict["auth"]["userpass"] = new_users_dict
+ with open(HYSTERIA_CONFIG_FILE, "w") as f:
+ f.write(json.dumps(hysteria_config_dict, indent=1))
+
+def sshvpn_user_purge(users_to_remove):
+ previous_users_list = sshvpn_get_users()
+ for user in previous_users_list:
+ if user in users_to_remove:
+ os.remove(f"{SSH_ROOT}/{user}.pub")
+ os.remove(f"{SSH_ROOT}/{user}")
+
+ # Overwrite existing authorized_key file
+ users_pubkey_files = [os.path.join(SSH_ROOT, i) for i in os.listdir(SSH_ROOT) if i.endswith(".pub")]
+ with open(AUTHORIZED_KEYS, "w") as f:
+ for pubkey_file in users_pubkey_files:
+ with open(pubkey_file, "r") as pkey:
+ f.write(pkey.read())
+
+def main():
+ current_unix_time = datetime.now().timestamp()
+
+ with open(EXPIRE_USER_JSON_PATH, "r") as f:
+ expire_user_dict = json.loads(f.read())
+ for exp in expire_user_dict.keys():
+ if float(exp) <= current_unix_time:
+ users = expire_user_dict[exp]
+
+ xray_user_purge(users)
+ sshvpn_user_purge(users)
+ ocserv_user_purge(users)
+ hysteria_user_purge(users)
+ with open(EXPIRE_USER_JSON_PATH, "w") as f:
+ f.write(json.dumps(expire_user_dict, indent=1))
+
+ with open(EXPIRE_WEB_JSON_PATH, "r") as f:
+ expire_web_dict = json.loads(f.read())
+ for exp in expire_web_dict.keys():
+ shutil.rmtree(f"/var/www/reactance/{exp}")
+
+if __name__ == "__main__":
+ main()