diff options
Diffstat (limited to 'roles/base')
| -rw-r--r-- | roles/base/handlers/main.yaml | 11 | ||||
| -rw-r--r-- | roles/base/tasks/add_pubkeys.yaml | 9 | ||||
| -rw-r--r-- | roles/base/tasks/base_setup.yaml | 58 | ||||
| -rw-r--r-- | roles/base/tasks/main.yaml | 12 | ||||
| -rw-r--r-- | roles/base/tasks/pre_execution_checks.yaml | 11 | ||||
| -rw-r--r-- | roles/base/tasks/setup_user_expiration.yaml | 19 | ||||
| -rw-r--r-- | roles/base/templates/newsyslog.conf.j2 | 31 | ||||
| -rw-r--r-- | roles/base/templates/syslog.conf.j2 | 21 | ||||
| -rw-r--r-- | roles/base/templates/user_expiration_control.py.j2 | 99 |
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() |
