preface

In Internet service, secondary domain name general resolution is a common technical solution. When I was designing a system for the company, I encountered a problem, that is, the domain name of the business is dynamically increasing and decreasing. And this service requires authentication management for all requests.

Therefore, IN the selection, I adopted the industry plan OpenResty + Redis for dynamic domain name resolution.

Dynamically resolve the prefix of the secondary domain name

Because of the generic resolution, we need to configure the domain name DNS to map *.domain.com to our proxy server.

Dynamic parsing requires a database to implement domain -> IP mapping, I consider two ways to save:

1. Reserved memory

2. redis

Considering memory unreliability and proxy server horizontal expansion, I used REDis to store these mappings.

Using the authentication mechanism of the main site, cookies are used directly.

Data acquisition: Query Data acquisition

local arg = ngx.req.get_uri_args()
arg['query parameter']

Copy the code

Database: Connect to Redis

local redis = require "resty.redis"
local redisClient = redis:new()
local ok, err = redisClient:connect(config.redisHost,config.redisPort)
if not ok then
    ngx.log(ngx.ERR, "failed to connect: ", err)
    return
end
redisClient:auth(config.redisPassword)
local host = ngx_re.split(ngx.var.host,"\ \.") [1]
local hostRes, err = redisClient:get(host)
Parsed data is returned
ngx.var.userdomain = hostRes
Copy the code

Authentication: Obtains cookie data

local userCookie = ngx.var.cookie_user
Copy the code

Cookie_user here refers to getting the key value of user from the cookie.

Nginx configuration

Configure the new server for resolution.

			# select this configuration when the domain name does not match the direction of the domain name
            listen 443 ssl;
            server_name *.yodfz.com;
            # Limit broadband size to 3MB per IP connection
            limit_conn_zone $binary_remote_addr zone=one:3m;
            ssl_certificate     /cert/1.crt;
            ssl_certificate_key /cert/2.key;
            ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
            ssl_ciphersHIGH:! aNULL:! MD5;gzip on;
            gzip_min_length 1k;
            gzip_buffers 4 16k;
            gzip_comp_level 2;
            gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
            gzip_vary off;
            gzip_disable "MSIE [1-6]\.";
            resolver 8.8.8.8 ipv6=off;
            location / {            
				# Official environment enabled
                lua_code_cache off;
                Set the $userdomain variable and its default value
                set $userdomain default;
                # import lua files
                rewrite_by_lua_file /lua/cname.lua;
                # Reverse proxy
                proxy_pass $userdomain;
                proxy_redirect off;
                proxy_buffering off;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
                # proxy_set_header Host $userdomain;
                # proxy_set_header X-Real-IP $remote_addr;
                # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }
Copy the code

Save the following file as cname.lua

local redis = require "resty.redis"
local resty_rsa = require "resty.rsa"
local ngx_re = require "ngx.re"
local cjson = require "cjson"
local config = require "lua.config"

local redisClient = redis:new()

-- Resolve secondary domain name to obtain inverse address from redis
local ok, err = redisClient:connect(config.redisHost,config.redisPort)
if not ok then
    ngx.log(ngx.ERR, "failed to connect: ", err)
    return
end
redisClient:auth(config.redisPassword)
local host = ngx_re.split(ngx.var.host,"\ \.")


local hostRes, err = redisClient:get(host[1])
if hostRes then
    ngx.var.userdomain = hostRes
    return
end

local ok, err = redisClient:set_keepalive(10000.100)
if not ok then
    ngx.say("failed to set keepalive: ", err)
    return
end
Copy the code