diff options
Diffstat (limited to 'roles/xray')
| -rw-r--r-- | roles/xray/handlers/main.yaml | 11 | ||||
| -rw-r--r-- | roles/xray/tasks/check_xray_exists.yaml | 21 | ||||
| -rw-r--r-- | roles/xray/tasks/configure_xray.yaml | 50 | ||||
| -rw-r--r-- | roles/xray/tasks/create_users_xray.yaml | 55 | ||||
| -rw-r--r-- | roles/xray/tasks/install_xray.yaml | 100 | ||||
| -rw-r--r-- | roles/xray/tasks/main.yaml | 3 | ||||
| -rw-r--r-- | roles/xray/templates/config.json.j2 | 131 | ||||
| -rw-r--r-- | roles/xray/templates/xray.rc.j2 | 22 |
8 files changed, 393 insertions, 0 deletions
diff --git a/roles/xray/handlers/main.yaml b/roles/xray/handlers/main.yaml new file mode 100644 index 00000000..63ee84c8 --- /dev/null +++ b/roles/xray/handlers/main.yaml @@ -0,0 +1,11 @@ +--- +- name: restart_xray + ansible.builtin.service: + name: xray + state: restarted + enabled: true + +- name: remove_xray_tempdir + ansible.builtin.file: + path: "{{ xray_tempdir.path }}" + state: absent diff --git a/roles/xray/tasks/check_xray_exists.yaml b/roles/xray/tasks/check_xray_exists.yaml new file mode 100644 index 00000000..c0fdc525 --- /dev/null +++ b/roles/xray/tasks/check_xray_exists.yaml @@ -0,0 +1,21 @@ +--- +- name: "Check if xray is already installed" + ansible.builtin.stat: + path: /var/reactance/xray + register: xray_directory + +- name: "Check if xray is configured" + ansible.builtin.stat: + path: /var/reactance/xray/etc/config.json + register: xray_config + +- name: "Install xray if directory doesn't exist" + ansible.builtin.include_tasks: install_xray.yaml + when: xray_directory.stat.exists == false + +- name: "Configure xray" + ansible.builtin.include_tasks: configure_xray.yaml + when: xray_config.stat.exists == false + +- name: "Create xray users" + ansible.builtin.include_tasks: create_users_xray.yaml diff --git a/roles/xray/tasks/configure_xray.yaml b/roles/xray/tasks/configure_xray.yaml new file mode 100644 index 00000000..4f8cf5e6 --- /dev/null +++ b/roles/xray/tasks/configure_xray.yaml @@ -0,0 +1,50 @@ +--- +# generate keypair, needed for config +- name: "generate private, public keypair for xtls-reality" + ansible.builtin.shell: "/var/reactance/xray/bin/xray x25519 | awk '{ print $3 }' | tr '\n' ','" + register: keypair + +- name: "set private key as var" + ansible.builtin.set_fact: + xray_private_key: "{{ (keypair.stdout | split(',')).0 }}" + xray_public_key: "{{ (keypair.stdout | split(',')).1 }}" + +- name: "write public key to file" + ansible.builtin.copy: + content: "{{ xray_public_key }}" + dest: "/var/reactance/xray/xray_public_key" + +- name: "write private key to file" + ansible.builtin.copy: + content: "{{ xray_private_key }}" + dest: "/var/reactance/xray/xray_private_key" + +- name: "template out config and init script" + ansible.builtin.template: + src: config.json.j2 + dest: "/var/reactance/xray/etc/config.json" + +# xray is chrooted and has their own mechanism for logging, which is why it needs to be separatly linked later +- name: "touch xray log files" + ansible.builtin.file: + path: "{{ item }}" + state: touch + mode: "0700" + owner: _vpn + group: _vpn + loop: + - "/var/reactance/xray/logs/xray-access.log" + - "/var/reactance/xray/logs/xray-error.log" + +# purely for convenience +- name: "link log files to /var/log/xray" + ansible.builtin.file: + src: "/var/reactance/xray/logs/{{ item }}" + dest: "/var/log/xray/{{ item }}" + state: link + mode: "0700" + owner: _vpn + group: _vpn + loop: + - xray-access.log + - xray-error.log diff --git a/roles/xray/tasks/create_users_xray.yaml b/roles/xray/tasks/create_users_xray.yaml new file mode 100644 index 00000000..b56cb0fa --- /dev/null +++ b/roles/xray/tasks/create_users_xray.yaml @@ -0,0 +1,55 @@ +--- + +- name: "get salamaner public key" + ansible.builtin.slurp: + path: "/var/reactance/xray/xray_public_key" + register: xray_pub_key_b64e + +- name: "vless user management" + xray: + users: "{{ all_users|default([]) + vless_users|default([]) }}" + protocol: vless + address: "{{ ansible_default_ipv4.interface|default(ansible_all_ipv4_addresses[0]) }}" + service_port: "{{ vless_port|default(4437) }}" + public_key: "{{ xray_pub_key_b64e.content|b64decode }}" + when: inventory_hostname in (groups['vless']|default([])) + (groups['all_vpns']|default([])) + register: vless_user_pass_dict + # no_log: true + notify: + - restart_xray + +- name: "vmess user management" + xray: + users: "{{ all_users|default([]) + vmess_users|default([]) }}" + protocol: vmess + address: "{{ ansible_default_ipv4.interface|default(ansible_all_ipv4_addresses[0]) }}" + service_port: "{{ vless_port|default(4437) }}" + public_key: "{{ xray_pub_key_b64e.content|b64decode }}" + when: inventory_hostname in (groups['vmess']|default([])) + (groups['all_vpns']|default([])) + register: vmess_user_pass_dict + no_log: true + notify: + - restart_xray + +- name: "trojan user management" + xray: + users: "{{ all_users|default([]) + trojan_users|default([]) }}" + protocol: trojan + address: "{{ ansible_default_ipv4.interface|default(ansible_all_ipv4_addresses[0]) }}" + service_port: "{{ vless_port|default(4437) }}" + public_key: "{{ xray_pub_key_b64e.content|b64decode }}" + when: inventory_hostname in (groups['trojan']|default([])) + (groups['all_vpns']|default([])) + register: trojan_user_pass_dict + no_log: true + notify: + - restart_xray + +- name: "make temp dir" + ansible.builtin.file: + path: /var/reactance/.temp/ + state: directory + +- name: "add ocserv user password pair to dict" + ansible.builtin.copy: + content: "{{ (trojan_user_pass_dict['msg']|default({}) | combine(vmess_user_pass_dict['msg']|default({}), vless_user_pass_dict['msg']|default({}), recursive=true, list_merge='append')) | to_json }}" + dest: /var/reactance/.temp/xray_user_pass_dict diff --git a/roles/xray/tasks/install_xray.yaml b/roles/xray/tasks/install_xray.yaml new file mode 100644 index 00000000..d4889531 --- /dev/null +++ b/roles/xray/tasks/install_xray.yaml @@ -0,0 +1,100 @@ +--- +- name: "create directory" + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: _vpn + group: _vpn + mode: 0700 + loop: + - "/var/reactance/xray" + - "/var/reactance/xray/bin" + - "/var/reactance/xray/etc" + - "/var/reactance/xray/logs" + - "/var/log/xray" + +- name: "install golang to build xray" + community.general.openbsd_pkg: + name: go-- + state: present + register: installed_go + +- name: "log var" + ansible.builtin.debug: + msg: "{{ is_installed }}" + +- name: "create temporary directory" + ansible.builtin.tempfile: + state: directory + suffix: temp + register: xray_tempdir + notify: + - remove_xray_tempdir + +- name: "get latest version" + ansible.builtin.shell: 'curl --silent "https://api.github.com/repos/XTLS/Xray-core/releases/latest" | jq -r .tag_name' + register: xray_latest_version + +- name: "download latest source" + ansible.builtin.get_url: + url: "https://github.com/XTLS/Xray-core/releases/download/{{ xray_latest_version.stdout }}/{{ xray_latest_version.stdout }}.zip" + dest: "{{ xray_tempdir.path }}/source.zip" + +- name: "additionally download latest version (for geoip.dat, geosite.dat)" + ansible.builtin.get_url: + url: "https://github.com/XTLS/Xray-core/releases/download/{{ xray_latest_version.stdout }}/Xray-openbsd-64.zip" + dest: "{{ xray_tempdir.path }}/xray.zip" + +- name: "unzip xray" + ansible.builtin.unarchive: + src: "{{ xray_tempdir.path }}/xray.zip" + dest: "{{ xray_tempdir.path }}" + remote_src: yes + +- name: "unzip xray source" + ansible.builtin.unarchive: + src: "{{ xray_tempdir.path }}/xray.source" + dest: "{{ xray_tempdir.path }}/source" + remote_src: yes + +- name: "build xray from source" + ansible.builtin.shell: "CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags=\"-s -w -buildid= -X 'xray.buf.readv='\" ./main" + args: + chdir: "{{ xray_tempdir.path }}/source" + +- name: "template out init script" + ansible.builtin.template: + src: "{{ item.file_src }}" + dest: "{{ item.file_dest }}" + loop: + - file_src: xray.rc.j2 + file_dest: "{{ xray_tempdir.path }}/xray.rc" + +- name: "install xray" + ansible.builtin.shell: "{{ item }}" + loop: + - "install -m 700 -o _vpn -g bin {{ xray_tempdir.path }}/source/xray /var/reactance/xray/bin/xray" + - "install -m 755 -o _vpn -g bin {{ xray_tempdir.path }}/xray.rc /etc/rc.d/xray" + - "install -m 700 -o _vpn -g bin {{ xray_tempdir.path }}/geoip.dat /var/reactance/xray/bin/geoip.dat" + - "install -m 700 -o _vpn -g bin {{ xray_tempdir.path }}/geosite.dat /var/reactance/xray/bin/geosite.dat" + +- name: "copy chroot dependencies" + ansible.builtin.shell: "deps=$(ldd /var/reactance/xray/bin/xray | awk 'FNR > 3 {print $7}'); for dep in $deps; do rsync -av --relative $dep /var/reactance/xray; done" + +# xray will fail without these two files +- name: "copy hosts and resolv.conf" + ansible.builtin.copy: + remote_src: true + src: "{{ item.src }}" + dest: "{{ item.dest }}" + loop: + - src: /etc/hosts + dest: /var/reactance/xray/etc/hosts + - src: /etc/resolv.conf + dest: /var/reactance/xray/etc/resolv.conf + +# - name: "uninstall golang (if wasn't installed in past)" +# community.general.openbsd_pkg: +# name: go-- +# state: present + diff --git a/roles/xray/tasks/main.yaml b/roles/xray/tasks/main.yaml new file mode 100644 index 00000000..422b2bb5 --- /dev/null +++ b/roles/xray/tasks/main.yaml @@ -0,0 +1,3 @@ +--- +- name: "setup xray vpn" + ansible.builtin.include_tasks: check_xray_exists.yaml diff --git a/roles/xray/templates/config.json.j2 b/roles/xray/templates/config.json.j2 new file mode 100644 index 00000000..35e78b75 --- /dev/null +++ b/roles/xray/templates/config.json.j2 @@ -0,0 +1,131 @@ +{ + "log": { + "loglevel": "debug", + "access": "/logs/xray-access.log", + "error": "/logs/xray-error.log", + "dnsLog": false + }, + "stats": {}, + "api": { + "tag": "api", + "services": [ + "StatsService" + ] + }, + "policy": { + "levels": { + "0": { + "statsUserUplink": true, + "statsUserDownlink": true + } + } + }, + "inbounds": [ +{% if inventory_hostname in (groups['trojan']|default([])) + (groups['all_vpns']|default([])) %} + { + "listen": "0.0.0.0", + "port": {{ trojan_port|default(4436) }}, + "protocol": "trojan", + "settings": { + "clients": [] + }, + "streamSettings": { + "network": "tcp", + "security": "reality", + "realitySettings": { + "show": false, + "dest": "behindthename.com:443", + "serverNames": [ + "behindthename.com", + "www.behindthename.com" + ], + "xver": 0, + "privateKey": "{{ xray_private_key }}", + "maxTimeDiff": 0, + "shortIds": [""] + } + } + }, +{% endif %} +{% if inventory_hostname in (groups['vless']|default([])) + (groups['all_vpns']|default([])) %} + { + "listen": "0.0.0.0", + "port": {{ vless_port|default(4437) }}, + "protocol": "vless", + "settings": { + "decryption": "none", + "clients": [] + }, + "streamSettings": { + "network": "tcp", + "security": "reality", + "realitySettings": { + "show": false, + "dest": "behindthename.com:443", + "serverNames": [ + "behindthename.com", + "www.behindthename.com" + ], + "xver": 0, + "privateKey": "{{ xray_private_key }}", + "maxTimeDiff": 0, + "shortIds": [""] + } + } + }, +{% endif %} +{% if inventory_hostname in (groups['vmess']|default([])) + (groups['all_vpns']|default([])) %} + { + "listen": "0.0.0.0", + "port": {{ vmess_port|default(4438) }}, + "protocol": "vmess", + "settings": { + "clients": [] + }, + "streamSettings": { + "network": "tcp", + "security": "reality", + "realitySettings": { + "show": false, + "dest": "behindthename.com:443", + "serverNames": [ + "behindthename.com", + "www.behindthename.com" + ], + "xver": 0, + "privateKey": "{{ xray_private_key }}", + "maxTimeDiff": 0, + "shortIds": [""] + } + } + }, +{% endif %} + { + "listen": "127.0.0.1", + "port": 10085, + "protocol": "dokodemo-door", + "settings": { + "address": "127.0.0.1" + }, + "tag": "api" + } + ], + "outbounds": [ + { + "protocol": "freedom", + "tag": "direct" + } + ], + "routing": { + "rules": [ + { + "inboundTag": [ + "api" + ], + "outboundTag": "api", + "type": "field" + } + ] + } +} + diff --git a/roles/xray/templates/xray.rc.j2 b/roles/xray/templates/xray.rc.j2 new file mode 100644 index 00000000..fe658fbc --- /dev/null +++ b/roles/xray/templates/xray.rc.j2 @@ -0,0 +1,22 @@ +#!/bin/ksh +# +# $OpenBSD: xray + +chroot_dir=/var/reactance/xray +chroot_user=_vpn +daemon_class=daemon +daemon=/bin/xray +daemon_flags="run -c /etc/config.json" +daemon_user=root + +. /etc/rc.d/rc.subr + +rc_start() { + rc_exec "chroot -u $chroot_user $chroot_dir $daemon $daemon_flags" +} + +rc_bg=YES +rc_reload=NO + +rc_cmd $1 + |
