Nginx as a forward proxy.
Nginx is commonly used as a reverse proxy, but it can also function as a forward proxy. There’s a project called ngx_http_proxy_connnect_module on GitHub that enables this functionality.
Let’s compile Nginx as a forward proxy and use it standalone.
If you need basic authentication, consider using OpenResty, which is more suitable for this purpose..
OpenResty is an enhanced version of Nginx that simplifies basic authentication using Lua scripts.
Compile the nginx with the connect module
Steps
#!/bin/bash
user_host=$SSH_USER@$SSH_HOST
openresty=openresty-1.25.3.1.tar.gz
if [[ -z $1 ]]; then
apt -q update && apt -q install -y build-essential libpcre3 libpcre3-dev libzip-dev libssl-dev apache2-utils
git clone https://github.com/chobits/ngx_http_proxy_connect_module.git
cd ngx_http_proxy_connect_module
wget https://openresty.org/download/$openresty
tar -xzf $openresty
cd openresty-1.25.3.1
./configure --prefix=/opt/openresty --add-module=../ --with-http_ssl_module
patch -d build/nginx-1.25.3/ -p 1 <../patch/proxy_connect_rewrite_102101.patch
#make CFLAGS="-Wno-deprecated-declarations" && make install
make && make install
fi
bash ./user-gen.sh
if [[ ! -d /opt/openresty/nginx/conf ]]; then
mkdir -p /opt/openresty/nginx/conf
fi
cp -f .htpasswd /opt/openresty/nginx/conf/.htpasswd-new
cp -f user.txt /opt/openresty/nginx/conf/user-new.txt
cp -f nginx.conf /opt/openresty/nginx/conf/
cp -f nginx-proxy.service /opt/openresty/nginx/
scp_wrap -r "/opt/openresty" "$user_host":/opt/
# run at your server.
export SSH_SCRIPT=$(
cat <<'EOF'
passwdfile=/opt/openresty/nginx/conf/.htpasswd
newpasswdfile=/opt/openresty/nginx/conf/.htpasswd-new
userfile=/opt/openresty/nginx/conf/user.txt
newuserfile=/opt/openresty/nginx/conf/user-new.txt
if [[ ! -f $passwdfile ]];then
touch $passwdfile
chmod 600 $passwdfile
fi
if [[ ! -f $userfile ]];then
touch $userfile
chmod 600 $userfile
fi
cat $newpasswdfile | tee -a $passwdfile
cat $newuserfile | tee -a $userfile
EOF
)
outputs=$(ssh_script $user_host)
# # build and copy
# #copy only
Go to lets-script and search ngx-connect-openresty
to build online.
copy the nginx.server
Copy the nginx.service from /lib/systemd/system/nginx.service to /etc/systemd/system/nginx-proxy.service.
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx-proxy.pid
ExecStartPre=/opt/openresty/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/opt/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/opt/openresty/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx-proxy.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
Edit nginx.conf
Edit the nginx.conf under the /opt/openresty/nginx/conf/nginx.conf
user www-data;
#worker_processes auto;
pid /run/nginx-proxy.pid;
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# Define a map to check for the presence of the Proxy-Authorization header
# Log messages from the Perl code
# error_log /var/log/nginx/error.log debug;
#error_log $auth_header debug;
# perl_require h/usr/local/nginx/conf/hello.pm;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 8443 ssl; ssl_certificate_key /etc/trojanweb/certs/gate.lets-script.com/gate.lets-script.com.key;
ssl_certificate /etc/trojanweb/certs/gate.lets-script.com/fullchain.cer;
ssl_session_cache shared:SSL:1m;
# dns resolver used by forward proxying
resolver 8.8.8.8;
# Check if authentication is required based on the presence of the Proxy-Authorization header
# forward proxy for CONNECT requests
proxy_connect;
proxy_connect_allow 443 563;
proxy_connect_connect_timeout 10s;
proxy_connect_data_timeout 10s;
rewrite_by_lua_block {
if not ngx.var.http_proxy_authorization then
ngx.header["Proxy-Authenticate"] = "Basic realm=\"Access to internal site\""
ngx.exit(407)
end
ngx.req.set_header("Authorization", ngx.var.http_proxy_authorization)
}
auth_basic "server auth";
auth_basic_user_file /opt/openresty/nginx/conf/.htpasswd;
# defined by yourself for non-CONNECT requests
# Example: reverse proxy for non-CONNECT requests
location / {
# Check if the Proxy-Authorization header is present
proxy_pass http://$host;
proxy_set_header Host $host;
# If backend wont check Auth header, we should not pass the user/password.
proxy_hide_header Authorization;
proxy_hide_header Proxy-Authorization;
}
}
}
Use the proxy
export https_proxy=https://username:[email protected]:8443
# or
export https_proxy=http://username:[email protected]:8080
IF you find WGET don’t work with https proxy, using http proxy instead. BECAUSE WGET invoke the CONNECT request with http.
If you want let CURL to use https, but let WGET use http, edit the ~/.wgetrc
file. or use
https_proxy=http://gate.lets-script.com:8080
use_proxy=on
proxy-user=username
proxy-password=password
How to handle special characters in username and password
URLencode the username and password.
export https_proxy='http://u+abc/d:+3hgkOLkQ@/OSQX6J@localhost:8090'