mirror of
https://github.com/Neur0toxine/shadowsocks-v2ray-wss.git
synced 2024-11-24 13:56:03 +03:00
Initial commit
This commit is contained in:
commit
400419b55b
32
.env.dist
Normal file
32
.env.dist
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Proxy password.
|
||||||
|
PASSWORD=B1922A0B-1D77-40C6-8119-497AB81BC7A4
|
||||||
|
|
||||||
|
# Encryption algorithm. Default is good enough for both powerful and low-end devices.
|
||||||
|
ENCRYPT=xchacha20-ietf-poly1305
|
||||||
|
|
||||||
|
# DNS servers which will be used by the proxy.
|
||||||
|
DNS_SERVERS=1.1.1.1,1.0.0.1
|
||||||
|
|
||||||
|
# Path to V2Ray. This path will be used during client configuration. I suggest using some random value, like CRC32.
|
||||||
|
V2_PATH=/v2ray
|
||||||
|
|
||||||
|
# Path to QR code and connection string. This will be accessible without any authentication, so, use long random string.
|
||||||
|
QR_PATH=/qr_code
|
||||||
|
|
||||||
|
# Set to "no" if you don't want to make connection data accessible via path provided in the previous value.
|
||||||
|
GENERATE_QR=yes
|
||||||
|
|
||||||
|
# Specify server domain here.
|
||||||
|
DOMAIN=example.com
|
||||||
|
|
||||||
|
# Specify server port here (443 is HIGHLY RECOMMENDED because HTTPS uses it).
|
||||||
|
PORT=443
|
||||||
|
|
||||||
|
# Path to domain's TLS ceritificate inside container.
|
||||||
|
TLS_CERT=/etc/ssl/ssl.pem
|
||||||
|
|
||||||
|
# Path to domain's TLS private key inside container.
|
||||||
|
TLS_KEY=/etc/ssl/ssl.key
|
||||||
|
|
||||||
|
# Path to dhparams.pem inside container. Can be generated automatically if it's not passed via volume or any other means.
|
||||||
|
TLS_DHPARAM=/etc/ssl/dhparams.pem
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
.env
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
ARG V2RAY_VERSION=v1.3.1
|
||||||
|
|
||||||
|
RUN set -ex \
|
||||||
|
&& apk add --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/testing wget libqrencode shadowsocks-libev nginx jq bash sudo \
|
||||||
|
&& mkdir -p /etc/shadowsocks-libev /v2raybin /wwwroot \
|
||||||
|
&& wget -O- "https://github.com/shadowsocks/v2ray-plugin/releases/download/${V2RAY_VERSION}/v2ray-plugin-linux-amd64-${V2RAY_VERSION}.tar.gz" | \
|
||||||
|
tar zx -C /v2raybin \
|
||||||
|
&& install /v2raybin/v2ray-plugin_linux_amd64 /usr/bin/v2ray-plugin \
|
||||||
|
&& rm -rf /v2raybin
|
||||||
|
|
||||||
|
COPY config/ /config
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
CMD /entrypoint.sh
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Shadowsocks + V2Ray in Docker
|
||||||
|
|
||||||
|
Preconfigured solution for running Shadowsocks proxy with V2Ray inside Docker container.
|
||||||
|
You'll need a working domain for this solution.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
1. Copy `.env.dist` to `.env`
|
||||||
|
2. Replace demo values with your own (especially password).
|
||||||
|
3. Add your domain certificate to the `cert.pem` file.
|
||||||
|
4. Add your domain private key to the `cert.key` file.
|
||||||
|
5. Generate dhparams.pem using command `openssl dhparam -out "${TLS_DHPARAM}" 4096` or just remove like `- ./dhparams.pem:${TLS_DHPARAM}` from the `docker-compose.yml`.
|
||||||
|
6. Run `docker-compose up -d`.
|
68
config/nginx.conf
Normal file
68
config/nginx.conf
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
user www-data;
|
||||||
|
worker_processes auto;
|
||||||
|
worker_cpu_affinity auto;
|
||||||
|
pcre_jit on;
|
||||||
|
pid /run/nginx.pid;
|
||||||
|
worker_rlimit_nofile 131072;
|
||||||
|
include /etc/nginx/modules-enabled/*.conf;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 4000;
|
||||||
|
multi_accept on;
|
||||||
|
use epoll;
|
||||||
|
epoll_events 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
|
||||||
|
##
|
||||||
|
# Basic Settings
|
||||||
|
##
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
keepalive_timeout 60;
|
||||||
|
client_body_timeout 12;
|
||||||
|
client_header_timeout 12;
|
||||||
|
send_timeout 30;
|
||||||
|
keepalive_requests 2000;
|
||||||
|
reset_timedout_connection on;
|
||||||
|
types_hash_max_size 2048;
|
||||||
|
server_tokens off;
|
||||||
|
server_names_hash_max_size 4096;
|
||||||
|
|
||||||
|
client_body_buffer_size 128K;
|
||||||
|
client_header_buffer_size 3m;
|
||||||
|
client_body_in_single_buffer on;
|
||||||
|
client_max_body_size 8m;
|
||||||
|
large_client_header_buffers 4 256k;
|
||||||
|
|
||||||
|
open_file_cache max=200000 inactive=20s;
|
||||||
|
open_file_cache_valid 30s;
|
||||||
|
open_file_cache_min_uses 2;
|
||||||
|
open_file_cache_errors on;
|
||||||
|
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
##
|
||||||
|
# Logging Settings
|
||||||
|
##
|
||||||
|
|
||||||
|
access_log off;
|
||||||
|
error_log /var/log/nginx/error.log crit;
|
||||||
|
|
||||||
|
##
|
||||||
|
# Gzip Settings
|
||||||
|
##
|
||||||
|
|
||||||
|
gzip off;
|
||||||
|
|
||||||
|
##
|
||||||
|
# Virtual Host Configs
|
||||||
|
##
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
include /etc/nginx/sites-available/*;
|
||||||
|
}
|
54
config/nginx_ss.conf.sh
Normal file
54
config/nginx_ss.conf.sh
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cat <<EOF
|
||||||
|
server {
|
||||||
|
listen ${PORT} ssl http2 reuseport backlog=131072 fastopen=256;
|
||||||
|
listen [::]:${PORT} ssl http2 reuseport backlog=131072 fastopen=256;
|
||||||
|
server_name ${DOMAIN}
|
||||||
|
add_header Allow "GET" always;
|
||||||
|
if ( \$request_method !~ ^(GET)$ ) {
|
||||||
|
return 444;
|
||||||
|
}
|
||||||
|
ssl_certificate ${TLS_CERT};
|
||||||
|
ssl_certificate_key ${TLS_KEY};
|
||||||
|
ssl_dhparam ${TLS_DHPARAM};
|
||||||
|
ssl_session_cache shared:le_nginx_SSL:1m;
|
||||||
|
ssl_session_cache shared:SSL:50m;
|
||||||
|
ssl_session_timeout 1d;
|
||||||
|
ssl_session_tickets off;
|
||||||
|
ssl_protocols TLSv1.3 TLSv1.2;
|
||||||
|
ssl_ecdh_curve secp384r1;
|
||||||
|
# ssl_early_data on;
|
||||||
|
add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always;
|
||||||
|
add_header Strict-Transport-Security 'max-age=63072000; includeSubdomains; preload' always;
|
||||||
|
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-Xss-Protection "1; mode=block" always;
|
||||||
|
resolver localhost valid=300s;
|
||||||
|
ssl_buffer_size 8k;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
|
||||||
|
root /wwwroot;
|
||||||
|
location / {
|
||||||
|
proxy_pass https://youtube.com;
|
||||||
|
limit_rate 1000k;
|
||||||
|
proxy_redirect off;
|
||||||
|
}
|
||||||
|
location ${QR_PATH} {
|
||||||
|
root /wwwroot;
|
||||||
|
}
|
||||||
|
location = ${V2_PATH} {
|
||||||
|
if (\$http_upgrade != "websocket") { # WebSocket return this when negotiation fails 404
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_pass http://127.0.0.1:2333;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host \$http_host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
17
config/shadowsocks-libev_config.json.sh
Normal file
17
config/shadowsocks-libev_config.json.sh
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cat <<EOF
|
||||||
|
{
|
||||||
|
"server": "127.0.0.1",
|
||||||
|
"server_port": "2333",
|
||||||
|
"password": ${PASSWORD_JSON},
|
||||||
|
"timeout": 300,
|
||||||
|
"method": "${ENCRYPT}",
|
||||||
|
"mode": "tcp_only",
|
||||||
|
"fast_open": true,
|
||||||
|
"nameserver": "${DNS_SERVERS}",
|
||||||
|
"reuse_port": true,
|
||||||
|
"no_delay": true,
|
||||||
|
"plugin": "v2ray-plugin",
|
||||||
|
"plugin_opts": "server;path=${V2_PATH};loglevel=none"
|
||||||
|
}
|
||||||
|
EOF
|
23
docker-compose.yml
Normal file
23
docker-compose.yml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
shadowsocks:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
environment:
|
||||||
|
PASSWORD: "${PASSWORD}"
|
||||||
|
ENCRYPT: "${ENCRYPT}"
|
||||||
|
V2_PATH: "${V2_PATH}"
|
||||||
|
QR_PATH: "${QR_PATH}"
|
||||||
|
GENERATE_QR: "${GENERATE_QR}"
|
||||||
|
DOMAIN: "${DOMAIN}"
|
||||||
|
PORT: ${PORT}
|
||||||
|
TLS_CERT: "${TLS_CERT}"
|
||||||
|
TLS_KEY: "${TLS_KEY}"
|
||||||
|
TLS_DHPARAM: "${TLS_DHPARAM}"
|
||||||
|
ports:
|
||||||
|
- "${PORT}:${PORT}"
|
||||||
|
volumes:
|
||||||
|
- ./cert.pem:${TLS_CERT}
|
||||||
|
- ./cert.key:${TLS_KEY}
|
||||||
|
- ./dhparams.pem:${TLS_DHPARAM}
|
||||||
|
restart: always
|
102
entrypoint.sh
Normal file
102
entrypoint.sh
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [[ -z "${PASSWORD}" ]]; then
|
||||||
|
export PASSWORD="B1922A0B-1D77-40C6-8119-497AB81BC7A4"
|
||||||
|
echo WARNING: Default password is being used! Please replace default password with you own.
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PASSWORD_JSON="$(echo -n "$PASSWORD" | jq -Rc)"
|
||||||
|
|
||||||
|
if [[ -z "${ENCRYPT}" ]]; then
|
||||||
|
export ENCRYPT="xchacha20-ietf-poly1305"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${V2_PATH}" ]]; then
|
||||||
|
export V2_PATH="/v2ray"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${QR_PATH}" ]]; then
|
||||||
|
export QR_PATH="/qr_code"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${GENERATE_QR}" ]]; then
|
||||||
|
export GENERATE_QR="yes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${PORT}" ]]; then
|
||||||
|
export PORT="443"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${DOMAIN}" ]]; then
|
||||||
|
export DOMAIN="localhost"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${DNS_SERVERS}" ]]; then
|
||||||
|
export DNS_SERVERS="1.1.1.1,1.0.0.1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${TLS_CERT}" ]]; then
|
||||||
|
export TLS_CERT="/etc/ssl/ssl.pem"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${TLS_KEY}" ]]; then
|
||||||
|
export TLS_KEY="/etc/ssl/ssl.key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${TLS_DHPARAM}" ]]; then
|
||||||
|
export TLS_DHPARAM="/etc/ssl/dhparams.pem"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo Proxy domain: ${DOMAIN}
|
||||||
|
echo Proxy port: ${PORT}
|
||||||
|
echo Proxy password: ${PASSWORD}
|
||||||
|
echo Encryption: ${ENCRYPT}
|
||||||
|
echo TLS certificate path: ${TLS_CERT}
|
||||||
|
echo TLS private key path: ${TLS_KEY}
|
||||||
|
echo dhparams path: ${TLS_DHPARAM}
|
||||||
|
echo Path to V2Ray: ${V2_PATH}
|
||||||
|
echo Path to QR code page: ${QR_PATH}
|
||||||
|
echo Generate QR code: ${GENERATE_QR}
|
||||||
|
|
||||||
|
if [[ ! -f "${TLS_DHPARAM}" ]]; then
|
||||||
|
echo Cannot find existing dhparams.pem, it will be generated now.
|
||||||
|
openssl dhparam -out "${TLS_DHPARAM}" 4096
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! id www-data &>/dev/null; then
|
||||||
|
adduser -s /bin/false -S -D -H www-data
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! id shadowsocks &>/dev/null; then
|
||||||
|
adduser -s /bin/false -S -D -H shadowsocks
|
||||||
|
fi
|
||||||
|
|
||||||
|
bash /config/shadowsocks-libev_config.json.sh > /etc/shadowsocks-libev/config.json
|
||||||
|
echo /etc/shadowsocks-libev/config.json has been updated with following contents:
|
||||||
|
cat /etc/shadowsocks-libev/config.json
|
||||||
|
echo
|
||||||
|
|
||||||
|
mkdir -p /etc/nginx/conf.d
|
||||||
|
mv /config/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
bash /config/nginx_ss.conf.sh > /etc/nginx/conf.d/ss.conf
|
||||||
|
echo /etc/nginx/conf.d/ss.conf has been updated with following contents:
|
||||||
|
cat /etc/nginx/conf.d/ss.conf
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ "$GENERATE_QR" = "yes" ]]; then
|
||||||
|
[ ! -d /wwwroot/${QR_PATH} ] && mkdir /wwwroot/${QR_PATH}
|
||||||
|
plugin=$(echo -n "v2ray;path=${V2_PATH};host=${DOMAIN};tls;fast-open" | sed -e 's/\//%2F/g' -e 's/=/%3D/g' -e 's/;/%3B/g')
|
||||||
|
ss="ss://$(echo -n ${ENCRYPT}:${PASSWORD} | base64 -w 0)@${DOMAIN}:${PORT}?plugin=${plugin}"
|
||||||
|
echo "<!DOCTYPE html><html><head><title>Shadowsocks Account</title></head><body>" > /wwwroot/${QR_PATH}/index.html
|
||||||
|
echo "<p>${ss}</p>" | tr -d '\n' >> /wwwroot/${QR_PATH}/index.html
|
||||||
|
echo "<img src=\"${QR_PATH}/vpn.png\">" >> /wwwroot/${QR_PATH}/index.html
|
||||||
|
echo "</body></html>" >> /wwwroot/${QR_PATH}/index.html
|
||||||
|
echo -n "${ss}" | qrencode -s 6 -o /wwwroot/${QR_PATH}/vpn.png
|
||||||
|
fi
|
||||||
|
|
||||||
|
chown www-data:www-data -R /wwwroot
|
||||||
|
echo Running nginx and shadowsocks proxy...
|
||||||
|
|
||||||
|
sudo -u shadowsocks ss-server -c /etc/shadowsocks-libev/config.json &
|
||||||
|
rm -rf /etc/nginx/sites-enabled/default
|
||||||
|
nginx -g 'daemon off;'
|
Loading…
Reference in New Issue
Block a user