mirror of
https://github.com/Neur0toxine/shadowsocks-v2ray-wss.git
synced 2024-11-28 07:46:07 +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