road to swarm support - needs a lot of testing

This commit is contained in:
bunkerity 2021-03-12 15:17:45 +01:00
parent 816fa47cbb
commit 95f7ca5b2d
19 changed files with 204 additions and 75 deletions

View File

@ -16,7 +16,7 @@ COPY lua/ /opt/lua
COPY prepare.sh /tmp/prepare.sh
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
EXPOSE 8080/tcp 8443/tcp

View File

@ -16,7 +16,7 @@ COPY lua/ /opt/lua
COPY prepare.sh /tmp/prepare.sh
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
EXPOSE 8080/tcp 8443/tcp

View File

@ -23,7 +23,7 @@ COPY lua/ /opt/lua
COPY prepare.sh /tmp/prepare.sh
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
EXPOSE 8080/tcp 8443/tcp

View File

@ -23,7 +23,7 @@ COPY lua/ /opt/lua
COPY prepare.sh /tmp/prepare.sh
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
EXPOSE 8080/tcp 8443/tcp

View File

@ -16,7 +16,7 @@ COPY lua/ /opt/lua
COPY prepare.sh /tmp/prepare.sh
RUN chmod +x /tmp/prepare.sh && /tmp/prepare.sh && rm -f /tmp/prepare.sh
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs
VOLUME /www /http-confs /server-confs /modsec-confs /modsec-crs-confs /cache /pre-server-confs /acme-challenge
EXPOSE 8080/tcp 8443/tcp

View File

@ -2,11 +2,11 @@ from Config import Config
class AutoConf :
def __init__(self, swarm) :
def __init__(self, swarm, api) :
self.__swarm = swarm
self.__instances = {}
self.__sites = {}
self.__config = Config(self.__swarm)
self.__config = Config(self.__swarm, api)
def pre_process(self, objs) :
for instance in objs :
@ -52,6 +52,12 @@ class AutoConf :
def __process_instance(self, instance, event, id, name, labels) :
if event == "create" :
self.__instances[id] = obj
if self.__swarm :
if self.__config.global(self.__instances) :
utils.log("[*] global config generated")
self.__config.reload(self.__instances)
else :
utils.log("[!] can't generate global config")
utils.log("[*] bunkerized-nginx instance created : " + name + " / " + id)
elif event == "start" :
self.__instances[id].reload()

View File

@ -5,8 +5,26 @@ import subprocess, shutil, os, traceback
class Config :
def __init__(self, swarm) :
def __init__(self, swarm, api) :
self.__swarm = swarm
self.__api = api
def global(self, instances) :
try :
for instance_id, instance in instances.items() :
env = instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]
break
vars
for var_value in env :
var = var_value.split("=")[0]
value = var_value.replace(var + "=", "", 1)
vars[var] = value
proc = subprocess.run(["/opt/entrypoint/global-config"], vars["SERVER_NAME"]], env=vars, capture_output=True)
return proc.returncode == 0
except Exception as e :
traceback.print_exc()
utils.log("[!] Error while generating config : " + str(e))
return False
def generate(self, instances, vars) :
try :
@ -27,7 +45,8 @@ class Config :
# Call site-config.sh to generate the config
proc = subprocess.run(["/opt/entrypoint/site-config.sh", vars["SERVER_NAME"]], env=vars_defaults, capture_output=True)
if proc.returncode == 0 :
return True
proc = subprocess.run(["/opt/entrypoint/multisite-config.sh"], capture_output=True)
return proc.returncode == 0
except Exception as e :
traceback.print_exc()
utils.log("[!] Error while generating config : " + str(e))
@ -43,7 +62,7 @@ class Config :
# Include the server conf
utils.replace_in_file("/etc/nginx/nginx.conf", "}", "include /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf;\n}")
return self.__reload(instances)
return self.reload(instances)
except Exception as e :
utils.log("[!] Error while activating config : " + str(e))
return False
@ -58,7 +77,7 @@ class Config :
# Remove the include
utils.replace_in_file("/etc/nginx/nginx.conf", "include /etc/nginx/" + vars["SERVER_NAME"] + "/server.conf;\n", "")
return self.__reload(instances)
return self.reload(instances)
except Exception as e :
utils.log("[!] Error while deactivating config : " + str(e))
@ -78,7 +97,7 @@ class Config :
utils.log("[!] Error while deactivating config : " + str(e))
return False
def __reload(self, instances) :
def reload(self, instances) :
ret = True
for instance_id, instance in instances.items() :
# Reload the instance object just in case
@ -91,11 +110,12 @@ class Config :
nodeID = task["NodeID"]
taskID = task["ID"]
fqdn = name + "." + nodeID + "." + taskID
req = requests.post("http://" + fqdn + ":8000/reload")
req = requests.post("http://" + fqdn + ":8080" + api + "/reload")
if req and req.status_code == 200 :
utils.log("[*] Sent reload order to instance " + fqdn + " (service.node.task)")
else :
utils.log("[!] Can't reload : API error for instance " + fqdn + " (service.node.task)")
ret = False
# Send SIGHUP to running instance
elif instance.status == "running" :
try :

View File

@ -1,18 +1,17 @@
FROM alpine
RUN apk add py3-pip apache2-utils bash && \
RUN apk add py3-pip apache2-utils bash certbot curl logrotate && \
pip3 install docker && \
mkdir /opt/entrypoint && \
mkdir -p /opt/confs/site
mkdir -p /opt/confs/site && \
mkdir -p /opt/confs/global
COPY confs/site/ /opt/confs/site
COPY confs/global/ /opt/confs/global
COPY entrypoint/* /opt/entrypoint/
COPY autoconf/* /opt/entrypoint/
RUN chmod +x /opt/entrypoint/*.py /opt/entrypoint/*.sh
# Fix CVE-2020-1971
RUN apk add "libcrypto1.1>1.1.1g-r0" "libssl1.1>1.1.1g-r0"
VOLUME /etc/nginx /etc/letsencrypt
VOLUME /etc/nginx
ENTRYPOINT ["/opt/entrypoint/entrypoint.py"]
ENTRYPOINT ["/opt/entrypoint/entrypoint.sh"]

View File

@ -18,11 +18,11 @@ except Exception as e :
# Check if we are in Swarm mode
swarm = os.getenv("SWARM_MODE") == "yes"
# Setup cron tasks if we are in Swarm mode
# TODO
# Our object to process events
autoconf = AutoConf(swarm)
api = ""
if swarm :
api = os.getenv("API_URI")
autoconf = AutoConf(swarm, api)
# Get all bunkerized-nginx instances and web services created before
try :

33
autoconf/entrypoint.sh Normal file
View File

@ -0,0 +1,33 @@
#!/bin/bash
echo "[*] Starting autoconf ..."
# trap SIGTERM and SIGINT
function trap_exit() {
echo "[*] Catched stop operation"
echo "[*] Stopping crond ..."
pkill -TERM crond
echo "[*] Stopping python3 ..."
pkill -TERM python3
pkill -TERM tail
}
trap "trap_exit" TERM INT QUIT
# remove old crontabs
echo "" > /etc/crontabs/root
# setup logrotate
touch /var/log/jobs.log
echo "0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.conf > /dev/null 2>&1" >> /etc/crontabs/root
# run autoconf app
/opt/entrypoint/app.py &
# display logs
tail -F /var/log/jobs.log &
pid="$!"
wait "$pid"
# stop
echo "[*] autoconf stopped"
exit 0

View File

@ -6,7 +6,6 @@ access_by_lua_block {
local use_whitelist_ip = %USE_WHITELIST_IP%
local use_whitelist_reverse = %USE_WHITELIST_REVERSE%
local use_user_agent = %USE_USER_AGENT%
local whitelist_useragent_list = { %WHITELIST_USERAGENT_LIST% }
local use_referrer = %USE_REFERRER%
local use_country = %USE_COUNTRY%
local use_blacklist_ip = %USE_BLACKLIST_IP%
@ -19,6 +18,7 @@ local use_antibot_captcha = %USE_ANTIBOT_CAPTCHA%
local use_antibot_recaptcha = %USE_ANTIBOT_RECAPTCHA%
-- include LUA code
local whitelist = require "whitelist"
local blacklist = require "blacklist"
local dnsbl = require "dnsbl"
@ -27,8 +27,9 @@ local javascript = require "javascript"
local captcha = require "captcha"
local recaptcha = require "recaptcha"
-- antibot
local antibot_uri = "%ANTIBOT_URI%"
-- user variables
local antibot_uri = "%ANTIBOT_URI%"
local whitelist_useragent_list = {%WHITELIST_USERAGENT_LIST%}
-- check if already in whitelist cache
if use_whitelist_ip and whitelist.ip_cached_ok() then

21
entrypoint/clamav.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# load default values
. /opt/entrypoint/defaults.sh
# load some functions
. /opt/entrypoint/utils.sh
# clamav setup
if [ "$(has_value USE_CLAMAV_UPLOAD yes)" != "" ] || [ "$USE_CLAMAV_SCAN" = "yes" ] ; then
echo "[*] Updating clamav (in background) ..."
freshclam > /dev/null 2>&1 &
echo "$CLAMAV_UPDATE_CRON /usr/bin/freshclam > /dev/null 2>&1" >> /etc/crontabs/root
fi
if [ "$USE_CLAMAV_SCAN" = "yes" ] ; then
if [ "$USE_CLAMAV_SCAN_REMOVE" = "yes" ] ; then
echo "$USE_CLAMAV_SCAN_CRON /usr/bin/clamscan -r -i --no-summary --remove / >> /var/log/clamav.log 2>&1" >> /etc/crontabs/root
else
echo "$USE_CLAMAV_SCAN_CRON /usr/bin/clamscan -r -i --no-summary / >> /var/log/clamav.log 2>&1" >> /etc/crontabs/root
fi
fi

View File

@ -12,7 +12,6 @@ done
# trap SIGTERM and SIGINT
function trap_exit() {
rm -f "/opt/running" 2> /dev/null
echo "[*] Catched stop operation"
echo "[*] Stopping crond ..."
pkill -TERM crond
@ -56,6 +55,19 @@ if [ ! -f "/opt/installed" ] ; then
# logs config
/opt/entrypoint/logs.sh
# lua config
# TODO : move variables from /usr/local/lib/lua + multisite support ?
/opt/entrypoint/lua.sh
# fail2ban config
/opt/entrypoint/fail2ban.sh
# clamav config
/opt/entrypoint/clamav.sh
# start temp nginx to solve Let's Encrypt challenges if needed
/opt/entrypoint/nginx-temp.sh
# only do config if we are not in swarm mode
if [ "$SWARM_MODE" = "no" ] ; then
# global config
@ -73,6 +85,7 @@ if [ ! -f "/opt/installed" ] ; then
echo "[*] Single site - $SERVER_NAME configuration done"
fi
fi
touch /opt/installed
else
echo "[*] Skipping configuration process"
@ -97,9 +110,12 @@ if [ "$SWARM_MODE" != "yes" ] ; then
done
fi
# stop temp config if needed
if [ -f "/tmp/nginx-temp.pid" ] ; then
nginx -c /etc/nginx/nginx-temp.conf -s quit
fi
# run nginx
echo "[*] Running nginx ..."
su -s "/usr/sbin/nginx" nginx
if [ "$?" -eq 0 ] ; then

20
entrypoint/fail2ban.sh Normal file
View File

@ -0,0 +1,20 @@
#!/bin/bash
# load default values
. /opt/entrypoint/defaults.sh
# load some functions
. /opt/entrypoint/utils.sh
# fail2ban setup
if [ "$(has_value USE_FAIL2BAN yes)" != "" ] ; then
rm -rf /etc/fail2ban/jail.d/*.conf
cp /opt/fail2ban/nginx-action.local /etc/fail2ban/action.d/nginx-action.local
cp /opt/fail2ban/nginx-filter.local /etc/fail2ban/filter.d/nginx-filter.local
cp /opt/fail2ban/nginx-jail.local /etc/fail2ban/jail.d/nginx-jail.local
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_BANTIME%" "$FAIL2BAN_BANTIME"
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_FINDTIME%" "$FAIL2BAN_FINDTIME"
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_MAXRETRY%" "$FAIL2BAN_MAXRETRY"
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_IGNOREIP%" "$FAIL2BAN_IGNOREIP"
replace_in_file "/etc/fail2ban/filter.d/nginx-filter.local" "%FAIL2BAN_STATUS_CODES%" "$FAIL2BAN_STATUS_CODES"
fi

View File

@ -7,7 +7,6 @@
. /opt/entrypoint/utils.sh
# copy stub confs
cp -r /opt/lua/* /usr/local/lib/lua
cp /opt/confs/global/* /etc/nginx/
# remove cron jobs
@ -18,12 +17,6 @@ if [ "$ADDITIONAL_MODULES" != "" ] ; then
apk add $ADDITIONAL_MODULES
fi
# start nginx with temp conf for let's encrypt challenges
if [ "$(has_value AUTO_LETS_ENCRYPT yes)" != "" ] ; then
replace_in_file "/etc/nginx/nginx-temp.conf" "%HTTP_PORT%" "$HTTP_PORT"
nginx -c /etc/nginx/nginx-temp.conf
fi
# include server block(s)
if [ "$MULTISITE" = "yes" ] ; then
includes=""
@ -196,8 +189,6 @@ if [ "$(has_value BLOCK_ABUSERS yes)" != "" ] ; then
fi
# DNS resolvers
resolvers=$(spaces_to_lua "$DNS_RESOLVERS")
replace_in_file "/usr/local/lib/lua/dns.lua" "%DNS_RESOLVERS%" "$resolvers"
replace_in_file "/etc/nginx/nginx.conf" "%DNS_RESOLVERS%" "$DNS_RESOLVERS"
# whitelist IP
@ -206,8 +197,6 @@ if [ "$(has_value USE_WHITELIST_IP yes)" != "" ] ; then
else
replace_in_file "/etc/nginx/nginx.conf" "%WHITELIST_IP_CACHE%" ""
fi
list=$(spaces_to_lua "$WHITELIST_IP_LIST")
replace_in_file "/usr/local/lib/lua/whitelist.lua" "%WHITELIST_IP_LIST%" "$list"
# whitelist rDNS
if [ "$(has_value USE_WHITELIST_REVERSE yes)" != "" ] ; then
@ -215,8 +204,6 @@ if [ "$(has_value USE_WHITELIST_REVERSE yes)" != "" ] ; then
else
replace_in_file "/etc/nginx/nginx.conf" "%WHITELIST_REVERSE_CACHE%" ""
fi
list=$(spaces_to_lua "$WHITELIST_REVERSE_LIST")
replace_in_file "/usr/local/lib/lua/whitelist.lua" "%WHITELIST_REVERSE_LIST%" "$list"
# blacklist IP
if [ "$(has_value USE_BLACKLIST_IP yes)" != "" ] ; then
@ -224,8 +211,6 @@ if [ "$(has_value USE_BLACKLIST_IP yes)" != "" ] ; then
else
replace_in_file "/etc/nginx/nginx.conf" "%BLACKLIST_IP_CACHE%" ""
fi
list=$(spaces_to_lua "$BLACKLIST_IP_LIST")
replace_in_file "/usr/local/lib/lua/blacklist.lua" "%BLACKLIST_IP_LIST%" "$list"
# blacklist rDNS
if [ "$(has_value USE_BLACKLIST_REVERSE yes)" != "" ] ; then
@ -233,8 +218,6 @@ if [ "$(has_value USE_BLACKLIST_REVERSE yes)" != "" ] ; then
else
replace_in_file "/etc/nginx/nginx.conf" "%BLACKLIST_REVERSE_CACHE%" ""
fi
list=$(spaces_to_lua "$BLACKLIST_REVERSE_LIST")
replace_in_file "/usr/local/lib/lua/blacklist.lua" "%BLACKLIST_REVERSE_LIST%" "$list"
# request limiting
if [ "$(has_value USE_LIMIT_REQ yes)" != "" ] ; then
@ -256,8 +239,6 @@ if [ "$(has_value USE_DNSBL yes)" != "" ] ; then
else
replace_in_file "/etc/nginx/nginx.conf" "%DNSBL_CACHE%" "lua_shared_dict dnsbl_cache 10m;"
fi
list=$(spaces_to_lua "$DNSBL_LIST")
replace_in_file "/usr/local/lib/lua/dnsbl.lua" "%DNSBL_LIST%" "$list"
# disable default site
if [ "$DISABLE_DEFAULT_SERVER" = "yes" ] && [ "$MULTISITE" = "yes" ] ; then
@ -269,36 +250,11 @@ fi
# fail2ban setup
if [ "$(has_value USE_FAIL2BAN yes)" != "" ] ; then
echo "" > /etc/nginx/fail2ban-ip.conf
rm -rf /etc/fail2ban/jail.d/*.conf
cp /opt/fail2ban/nginx-action.local /etc/fail2ban/action.d/nginx-action.local
cp /opt/fail2ban/nginx-filter.local /etc/fail2ban/filter.d/nginx-filter.local
cp /opt/fail2ban/nginx-jail.local /etc/fail2ban/jail.d/nginx-jail.local
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_BANTIME%" "$FAIL2BAN_BANTIME"
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_FINDTIME%" "$FAIL2BAN_FINDTIME"
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_MAXRETRY%" "$FAIL2BAN_MAXRETRY"
replace_in_file "/etc/fail2ban/jail.d/nginx-jail.local" "%FAIL2BAN_IGNOREIP%" "$FAIL2BAN_IGNOREIP"
replace_in_file "/etc/fail2ban/filter.d/nginx-filter.local" "%FAIL2BAN_STATUS_CODES%" "$FAIL2BAN_STATUS_CODES"
fi
# clamav setup
if [ "$(has_value USE_CLAMAV_UPLOAD yes)" != "" ] || [ "$USE_CLAMAV_SCAN" = "yes" ] ; then
echo "[*] Updating clamav (in background) ..."
freshclam > /dev/null 2>&1 &
echo "$CLAMAV_UPDATE_CRON /usr/bin/freshclam > /dev/null 2>&1" >> /etc/crontabs/root
fi
if [ "$USE_CLAMAV_SCAN" = "yes" ] ; then
if [ "$USE_CLAMAV_SCAN_REMOVE" = "yes" ] ; then
echo "$USE_CLAMAV_SCAN_CRON /usr/bin/clamscan -r -i --no-summary --remove / >> /var/log/clamav.log 2>&1" >> /etc/crontabs/root
else
echo "$USE_CLAMAV_SCAN_CRON /usr/bin/clamscan -r -i --no-summary / >> /var/log/clamav.log 2>&1" >> /etc/crontabs/root
fi
fi
# CrowdSec setup
if [ "$(has_value USE_CROWDSEC yes)" != "" ] ; then
replace_in_file "/etc/nginx/nginx.conf" "%USE_CROWDSEC%" "include /etc/nginx/crowdsec.conf;"
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_HOST%" "$CROWDSEC_HOST"
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_KEY%" "$CROWDSEC_KEY"
else
replace_in_file "/etc/nginx/nginx.conf" "%USE_CROWDSEC%" ""
fi

40
entrypoint/lua.sh Normal file
View File

@ -0,0 +1,40 @@
#!/bin/bash
# load default values
. /opt/entrypoint/defaults.sh
# load some functions
. /opt/entrypoint/utils.sh
# copy stub LUA scripts
cp -r /opt/lua/* /usr/local/lib/lua
# DNS resolvers
resolvers=$(spaces_to_lua "$DNS_RESOLVERS")
replace_in_file "/usr/local/lib/lua/dns.lua" "%DNS_RESOLVERS%" "$resolvers"
# whitelist IP
list=$(spaces_to_lua "$WHITELIST_IP_LIST")
replace_in_file "/usr/local/lib/lua/whitelist.lua" "%WHITELIST_IP_LIST%" "$list"
# whitelist rDNS
list=$(spaces_to_lua "$WHITELIST_REVERSE_LIST")
replace_in_file "/usr/local/lib/lua/whitelist.lua" "%WHITELIST_REVERSE_LIST%" "$list"
# blacklist IP
list=$(spaces_to_lua "$BLACKLIST_IP_LIST")
replace_in_file "/usr/local/lib/lua/blacklist.lua" "%BLACKLIST_IP_LIST%" "$list"
# blacklist rDNS
list=$(spaces_to_lua "$BLACKLIST_REVERSE_LIST")
replace_in_file "/usr/local/lib/lua/blacklist.lua" "%BLACKLIST_REVERSE_LIST%" "$list"
# DNSBL
list=$(spaces_to_lua "$DNSBL_LIST")
replace_in_file "/usr/local/lib/lua/dnsbl.lua" "%DNSBL_LIST%" "$list"
# CrowdSec setup
if [ "$(has_value USE_CROWDSEC yes)" != "" ] ; then
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_HOST%" "$CROWDSEC_HOST"
replace_in_file "/usr/local/lib/lua/crowdsec/crowdsec.conf" "%CROWDSEC_KEY%" "$CROWDSEC_KEY"
fi

19
entrypoint/nginx-temp.sh Normal file
View File

@ -0,0 +1,19 @@
#!/bin/bash
# load default values
. /opt/entrypoint/defaults.sh
# load some functions
. /opt/entrypoint/utils.sh
# start nginx with temp conf for let's encrypt challenges
if [ "$(has_value AUTO_LETS_ENCRYPT yes)" != "" ] ; then
cp /opt/confs/global/nginx-temp.conf /tmp/nginx-temp.conf
replace_in_file "/tmp/nginx-temp.conf" "%HTTP_PORT%" "$HTTP_PORT"
nginx -c /tmp/nginx-temp.conf
if [ "$?" -eq 0 ] ; then
echo "[*] Successfully started temp nginx to solve Let's Encrypt challenges"
else
echo "[!] Can't start temp nginx to solve Let's Encrypt challenges"
fi
fi

View File

@ -1,9 +1,7 @@
#!/bin/bash
# load default values
set -a
. /opt/entrypoint/defaults.sh
set +a
# load some functions
. /opt/entrypoint/utils.sh

View File

@ -1,6 +1,6 @@
local M = {}
local resolver = require "resty.dns.resolver"
local resolvers = {%DNS_RESOLVERS%}
local resolvers = {%DNS_RESOLVERS%}
local ip = ngx.var.remote_addr
function M.get_reverse()