diff --git a/playbooks/xray-test.yml b/playbooks/xray-test.yml new file mode 100644 index 0000000..e93c435 --- /dev/null +++ b/playbooks/xray-test.yml @@ -0,0 +1,5 @@ +--- +- hosts: router + become: yes + roles: + - xray-core diff --git a/roles/xray-core/files/dns.jsonc b/roles/xray-core/files/dns.jsonc new file mode 100644 index 0000000..74c6bf9 --- /dev/null +++ b/roles/xray-core/files/dns.jsonc @@ -0,0 +1,7 @@ +{ + "dns": { + "tag": "dns-in", + "servers": ["localhost"], + "queryStrategy": "UseIPv4" + } +} diff --git a/roles/xray-core/files/inbounds.jsonc b/roles/xray-core/files/inbounds.jsonc new file mode 100644 index 0000000..b928bb4 --- /dev/null +++ b/roles/xray-core/files/inbounds.jsonc @@ -0,0 +1,35 @@ +{ + "inbounds": [ + { + "port": 61219, + "listen": "127.0.0.1", + "protocol": "dokodemo-door", + "settings": { + "followRedirect": true, + "network": "tcp,udp" + }, + "streamSettings": { + "sockopt": { + "tproxy": "tproxy" + } + }, + "tag": "tproxy" + }, + { + "tag": "socks-in", + "ip": "127.0.0.1", + "port": 1080, + "protocol": "socks", + "settings": { + "auth": "password", + "accounts": [ + { + "user": "embargo", + "pass": "moistnes12" + } + ], + "udp": true + } + } + ] +} diff --git a/roles/xray-core/files/log.jsonc b/roles/xray-core/files/log.jsonc new file mode 100644 index 0000000..f00262b --- /dev/null +++ b/roles/xray-core/files/log.jsonc @@ -0,0 +1,9 @@ +{ + "log": { + "access": "/var/log/xray-core/access.log", + "error": "/var/log/xray-core/error.log", + "loglevel": "warning", + "dnsLog": false, + "maskAddress": "" + } +} diff --git a/roles/xray-core/files/policy.jsonc b/roles/xray-core/files/policy.jsonc new file mode 100644 index 0000000..4c4da45 --- /dev/null +++ b/roles/xray-core/files/policy.jsonc @@ -0,0 +1,23 @@ +{ + "policy": { + "levels": { + "0": { + + "handshake": 4, + "connIdle": 300, + "uplinkOnly": 2, + "downlinkOnly": 5, + "statsUserUplink": false, + "statsUserDownlink": false, + "statsUserOnline": false, + "bufferSize": 512 + } + }, + "system": { + "statsInboundUplink": false, + "statsInboundDownlink": false, + "statsOutboundUplink": false, + "statsOutboundDownlink": false + } + } +} diff --git a/roles/xray-core/handlers/main.yml b/roles/xray-core/handlers/main.yml new file mode 100644 index 0000000..398546e --- /dev/null +++ b/roles/xray-core/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: restart xray-core + ansible.builtin.service: + name: xray-core + state: restarted + listen: restart xray-core diff --git a/roles/xray-core/tasks/configure.yml b/roles/xray-core/tasks/configure.yml new file mode 100644 index 0000000..ab2f83f --- /dev/null +++ b/roles/xray-core/tasks/configure.yml @@ -0,0 +1,33 @@ +--- +- name: ensure /etc/xray-core exists + ansible.builtin.file: + path: /etc/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: "/etc/xray-core/config/{{ item }}" + mode: "0744" + loop: + - dns.jsonc + - inbounds.jsonc + - log.jsonc + - policy.jsonc + +- name: deploy dynamic xray-core config + ansible.builtin.template: + src: "{{ item }}.j2" + dest: "/etc/xray-core/config/{{ item }}" + mode: "0744" + loop: + - observatory.jsonc + - outbounds.jsonc + - routing.jsonc diff --git a/roles/xray-core/tasks/install.yml b/roles/xray-core/tasks/install.yml new file mode 100644 index 0000000..bf9843b --- /dev/null +++ b/roles/xray-core/tasks/install.yml @@ -0,0 +1,5 @@ +--- +- name: install unbound + ansible.builtin.package: + name: unbound + state: present diff --git a/roles/xray-core/tasks/main.yml b/roles/xray-core/tasks/main.yml new file mode 100644 index 0000000..2f87337 --- /dev/null +++ b/roles/xray-core/tasks/main.yml @@ -0,0 +1,6 @@ +--- +#- name: include unbound install +# ansible.builtin.include_tasks: install.yml + +- name: include xray-core configurure + ansible.builtin.include_tasks: configure.yml diff --git a/roles/xray-core/templates/observatory.jsonc.j2 b/roles/xray-core/templates/observatory.jsonc.j2 new file mode 100644 index 0000000..ada6f06 --- /dev/null +++ b/roles/xray-core/templates/observatory.jsonc.j2 @@ -0,0 +1,8 @@ +{ + "observatory": { + "subjectSelector": ["vless-"], + "probeUrl": "https://www.google.com/generate_204", + "probeInterval": "30s", + "enableConcurrency": true + } +} diff --git a/roles/xray-core/templates/outbounds.jsonc.j2 b/roles/xray-core/templates/outbounds.jsonc.j2 new file mode 100644 index 0000000..dbf1b47 --- /dev/null +++ b/roles/xray-core/templates/outbounds.jsonc.j2 @@ -0,0 +1,67 @@ +{ + "outbounds": [ +{% for item in xray_outbounds %} + { + "tag": "vless-{{ item.tag }}", + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "{{ item.address }}", + "port": 443, + "users": [ + { + "id": "{{ xray_id }}", + "flow": "xtls-rprx-vision", + "encryption": "{{ xray_encryption }}" + } + ] + } + ], + "domainStrategy": "UseIPv4" + }, + "streamSettings": { + "network": "xhttp", + "xhttpSettings": { + "path": "{{ xray_xhttp_path }}", + "mode": "stream-one" + }, + "security": "tls", + "tlsSettings": { + "alpn": [ + "h2", + "h3" + ], + "fingerprint": "firefox" + }, + "sockopt": { + "mark": 255 + } + } + }, +{% endfor %} + { + "tag": "direct", + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv4" + }, + "streamSettings": { + "sockopt": { + "mark": 255, + "interface": "eth1", + "tcpFastOpen": true + } + } + }, + { + "tag": "blocked", + "protocol": "blackhole", + "settings": { + "response": { + "type": "none" + } + } + } + ] +} diff --git a/roles/xray-core/templates/routing.jsonc.j2 b/roles/xray-core/templates/routing.jsonc.j2 new file mode 100644 index 0000000..fa0b51d --- /dev/null +++ b/roles/xray-core/templates/routing.jsonc.j2 @@ -0,0 +1,41 @@ +{ + "routing": { + "domainStrategy": "IPIfNonMatch", +{% if xray_outbounds | length > 1 %} + "balancers": [ + { + "tag": "balancer-vless", + "selector": ["vless-"], + "strategy": { + "type": "leastLoad", + "settings": { + "costs": [ +{% for item in xray_outbounds %} + { + "match": "vless-{{ item.tag }}", + "value": {{ item.value }} + }{{ "," if not loop.last else "" }} +{% endfor %} + ] + } + } + } + ], +{% endif %} + "rules": [ + { + "type": "field", + "protocol": ["bittorrent"], + "outboundTag": "direct" + }, + { + "type": "field", + "inboundTag": [ + "tproxy", + "socks-in" + ], + "balancerTag": "{{ 'balancer-vless' if xray_outbounds | length > 1 else 'vless-' ~ xray_outbounds[0].tag }}" + } + ] + } +}