xray support

This commit is contained in:
quackerd 2021-02-01 01:07:23 -05:00
parent 9276361ac5
commit f1672986c4
Signed by: d
GPG Key ID: F73412644EDE357A
6 changed files with 75 additions and 39 deletions

View File

@ -1,6 +1,5 @@
{ {
"id": "{{ id }}", "id": "{{ id }}",
"flow": "xtls-rprx-direct", "flow": "{{ flow }}",
"level": 0, "level": 0
"email": "dummy@dummy.com"
} }

View File

@ -22,20 +22,21 @@ server:
clients: clients:
# name: the name of the client, cannot be null # name: the name of the client, cannot be null
- name: example_user1 - name: example_user1
# id: the uuid of each user # id: the password(uuid) of each user
# default: auto-generated uuid # default: auto-generated random string
# comment: for a managed environment we recommend hardcoding the id: # comment: for a managed environment we recommend hardcoding the id
# the generated id does NOT currently back-propagate to this file # the generated id does NOT currently back-propagate to this file
# you WILL lose existing users if you run configure.py multiple times with blank ids as they will be regenerated with random ids # you WILL lose existing users if you run configure.py multiple times with blank ids as they will be regenerated with random ids
id: ahaha # NOTE THAT id DOES NOT have to be UUID, can be any string (supported by upstream xray)
# alterid: the alterid as appeared in v2ray config file id:
# default: 64 # flow: the flow parameter of each user
alterid: # default: xtls-rprx-direct
flow:
# port: local socks5 proxy port on clients' machines # port: local socks5 proxy port on clients' machines
# default: 1080 # default: 1080
port: port:
# you can also set each field manually like below: # you can also set each field manually like below:
- name: example_user2 - name: example_user2
id: 5058b990-6be5-438d-9c02-4b06b5d927d0 id: example_passwd2
alterid: 32 flow: xtls-rprx-direct
port: 6666 port: 6666

View File

@ -13,18 +13,18 @@ CLIENT_OUTPUT_DIR = "clients"
DEFAULT_EMAIL = "dummy@dummy.org" DEFAULT_EMAIL = "dummy@dummy.org"
CONF_FILE = "config.yml" CONF_FILE = "config.yml"
SERVER_IN = "server.in" SERVER_IN = "server.in"
SERVER_PATH = "v2ray" SERVER_PATH = "xray"
SERVER_FN = "config.json" SERVER_FN = "config.json"
NGINX_IN = "nginx.in" NGINX_IN = "nginx.in"
NGINX_PATH = "nginx" NGINX_PATH = "nginx"
NGINX_FN = "default" NGINX_FN = "default"
DEFAULT_ALTERID = 64
CLIENT_OBJ_IN = "client_obj.in" CLIENT_OBJ_IN = "client_obj.in"
CLIENT_CONF_IN = "client_conf.in" CLIENT_CONF_IN = "client_conf.in"
DOCKER_IN = "docker-compose.in" DOCKER_IN = "docker-compose.in"
WATCHTOWER_IN = "watchtower.in" WATCHTOWER_IN = "watchtower.in"
DEFAULT_WATCHTOWER_ENABLE = False DEFAULT_WATCHTOWER_ENABLE = False
DEFAULT_CLIENT_PORT = 1080 DEFAULT_CLIENT_PORT = 1080
DEFAULT_USER_FLOW = "xtls-rprx-direct"
def yaml_key_exists_else(mapping : [], name : str, other_val = None, nullable = True): def yaml_key_exists_else(mapping : [], name : str, other_val = None, nullable = True):
if (name in mapping) and (mapping[name] != None): if (name in mapping) and (mapping[name] != None):
@ -35,11 +35,15 @@ def yaml_key_exists_else(mapping : [], name : str, other_val = None, nullable =
else: else:
return other_val return other_val
def random_string(stringLength=16):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
class Client: class Client:
def __init__(self, conf_obj): def __init__(self, conf_obj):
self.name = str(yaml_key_exists_else(conf_obj, 'name', nullable=False)) self.name = str(yaml_key_exists_else(conf_obj, 'name', nullable=False))
self.id = str(yaml_key_exists_else(conf_obj, 'id', other_val=uuid.uuid4())) self.id = str(yaml_key_exists_else(conf_obj, 'id', other_val=random_string()))
self.alterid = int(yaml_key_exists_else(conf_obj,'alterid', other_val=DEFAULT_ALTERID)) self.flow = str(yaml_key_exists_else(conf_obj, 'flow', other_val=DEFAULT_USER_FLOW))
self.port = int(yaml_key_exists_else(conf_obj, 'port', other_val=DEFAULT_CLIENT_PORT)) self.port = int(yaml_key_exists_else(conf_obj, 'port', other_val=DEFAULT_CLIENT_PORT))
def print(self, ident): def print(self, ident):
@ -49,18 +53,13 @@ class Client:
print(pre + "{") print(pre + "{")
print(pre + " id: " + self.id) print(pre + " id: " + self.id)
print(pre + " alterid: " + str(self.alterid)) print(pre + " flow: " + self.flow)
print(pre + " port: " + str(self.port)) print(pre + " port: " + str(self.port))
print(pre + "}") print(pre + "}")
class Config: class Config:
@staticmethod
def __randomString(stringLength=16):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
def print(self): def print(self):
print("Server configuration:") print("Server configuration:")
print(" domain: " + self.domain) print(" domain: " + self.domain)
@ -83,7 +82,7 @@ class Config:
self.subdomain_only = len(self.subdomain) > 0 self.subdomain_only = len(self.subdomain) > 0
self.uid = int(yaml_key_exists_else(conf_srv, 'uid', other_val=os.getuid())) self.uid = int(yaml_key_exists_else(conf_srv, 'uid', other_val=os.getuid()))
self.gid = int(yaml_key_exists_else(conf_srv, 'gid', other_val=os.getgid())) self.gid = int(yaml_key_exists_else(conf_srv, 'gid', other_val=os.getgid()))
self.path = str(yaml_key_exists_else(conf_srv, 'path', other_val=self.__randomString())) self.path = str(yaml_key_exists_else(conf_srv, 'path', other_val=random_string()))
self.watchtower = bool(yaml_key_exists_else(conf_srv, 'watchtower', other_val=DEFAULT_WATCHTOWER_ENABLE)) self.watchtower = bool(yaml_key_exists_else(conf_srv, 'watchtower', other_val=DEFAULT_WATCHTOWER_ENABLE))
self.clients = [] self.clients = []
@ -118,7 +117,7 @@ def main():
if i > 0: if i > 0:
clients += ",\n" clients += ",\n"
clients += jinja2.Template(client_obj).render(id = conf.clients[i].id, clients += jinja2.Template(client_obj).render(id = conf.clients[i].id,
alterid = conf.clients[i].alterid) flow = conf.clients[i].flow)
template_dict['clients'] = clients template_dict['clients'] = clients
print("Generating files...") print("Generating files...")
@ -150,8 +149,8 @@ def main():
for i in range(len(conf.clients)): for i in range(len(conf.clients)):
template_dict['id'] = conf.clients[i].id template_dict['id'] = conf.clients[i].id
template_dict['port'] = conf.clients[i].port template_dict['port'] = conf.clients[i].port
template_dict['alterid'] = conf.clients[i].alterid template_dict['flow'] = conf.clients[i].flow
epath = os.path.join(path, conf.clients[i].name + "_" + conf.clients[i].id) epath = os.path.join(path, conf.clients[i].name)
os.makedirs(epath, exist_ok=True) os.makedirs(epath, exist_ok=True)
with open(os.path.join(epath, SERVER_FN), "w") as f: with open(os.path.join(epath, SERVER_FN), "w") as f:
f.write(client_conf_temp.render(template_dict)) f.write(client_conf_temp.render(template_dict))

View File

@ -1,18 +1,26 @@
version: '3.0' version: '3.0'
networks: networks:
br-xray: br-d2ray:
external: false external: false
driver: bridge
driver_opts:
com.docker.network.bridge.name: br-d2ray
enable_ipv6: false
ipam:
driver: default
config:
- subnet: 172.127.127.0/24
services: services:
nginx: d2ray_nginx:
container_name: xray_nginx container_name: d2ray_nginx
image: linuxserver/swag image: linuxserver/swag
restart: unless-stopped restart: unless-stopped
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN
networks: networks:
- br-xray - br-d2ray
environment: environment:
- PUID={{ uid }} - PUID={{ uid }}
- PGID={{ gid }} - PGID={{ gid }}
@ -27,17 +35,26 @@ services:
ports: ports:
- 80:80 - 80:80
volumes: volumes:
- ./certs:/etc/letsencrypt/live/{{ domain }} - ./nginx:/config
v2ray: healthcheck:
container_name: xray_xray test: ["CMD", "curl", "-f", "http://{{ subdomain }}.{{ domain }}:80"]
interval: 5s
timeout: 3s
retries: 30
d2ray_xray:
container_name: d2ray_xray
image: teddysun/xray image: teddysun/xray
restart: unless-stopped restart: unless-stopped
depends_on:
d2ray_nginx:
condition: service_healthy
networks: networks:
- br-v2ray - br-v2ray
ports: ports:
- 443:443 - 443:443
volumes: volumes:
- ./xray/config.json:/etc/xray/config.json - ./nginx/etc:/le-etc
- ./certs:/certs - ./xray:/etc/xray
{{ watchtower }} {{ watchtower }}

14
nginx.in Normal file
View File

@ -0,0 +1,14 @@
server {
listen 80 default_server;
server_name {{ subdomain }}.{{ domain }};
if ($remote_addr = 127.0.0.1) {
root /config/www;
index index.html index.htm index.php;
}
if ($remote_addr != 127.0.0.1) {
return 301 https://$host$request_uri;
}
}

View File

@ -1,4 +1,9 @@
{ {
"log": {
"loglevel": "warning",
"access": "/etc/xray/access.log",
"error": "/etc/xray/error.log"
},
"inbounds": [ "inbounds": [
{ {
"port": 443, "port": 443,
@ -10,7 +15,7 @@
"decryption": "none", "decryption": "none",
"fallbacks": [ "fallbacks": [
{ {
"dest": "xray_nginx:80" "dest": "d2ray_nginx:80"
} }
] ]
}, },
@ -18,10 +23,11 @@
"network": "tcp", "network": "tcp",
"security": "xtls", "security": "xtls",
"xtlsSettings": { "xtlsSettings": {
"certificates:": [ "alpn": ["http/1.1", "h2"],
"certificates": [
{ {
"certificateFile": "/certs/fullchain.pem", "certificateFile": "/le-etc/letsencrypt/live/{{ subdomain }}.{{ domain }}/fullchain.pem",
"keyFile": "/certs/privkey.pem" "keyFile": "/le-etc/letsencrypt/live/{{ subdomain }}.{{ domain }}/privkey.pem"
} }
] ]
} }