summaryrefslogtreecommitdiff
path: root/roles/xray
diff options
context:
space:
mode:
Diffstat (limited to 'roles/xray')
-rw-r--r--roles/xray/handlers/main.yaml11
-rw-r--r--roles/xray/tasks/check_xray_exists.yaml21
-rw-r--r--roles/xray/tasks/configure_xray.yaml50
-rw-r--r--roles/xray/tasks/create_users_xray.yaml55
-rw-r--r--roles/xray/tasks/install_xray.yaml100
-rw-r--r--roles/xray/tasks/main.yaml3
-rw-r--r--roles/xray/templates/config.json.j2131
-rw-r--r--roles/xray/templates/xray.rc.j222
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
+