/
lua_ingress.lua
133 lines (107 loc) · 3.42 KB
/
lua_ingress.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
local ngx_re_split = require("ngx.re").split
local original_randomseed = math.randomseed
local string_format = string.format
local ngx_redirect = ngx.redirect
local _M = {}
local seeds = {}
-- general Nginx configuration passed by controller to be used in this module
local config
local function get_seed_from_urandom()
local seed
local frandom, err = io.open("/dev/urandom", "rb")
if not frandom then
ngx.log(ngx.WARN, 'failed to open /dev/urandom: ', err)
return nil
end
local str = frandom:read(4)
frandom:close()
if not str then
ngx.log(ngx.WARN, 'failed to read data from /dev/urandom')
return nil
end
seed = 0
for i = 1, 4 do
seed = 256 * seed + str:byte(i)
end
return seed
end
math.randomseed = function(seed)
local pid = ngx.worker.pid()
if seeds[pid] then
ngx.log(ngx.WARN,
string.format("ignoring math.randomseed(%d) since PRNG is already seeded for worker %d", seed, pid))
return
end
original_randomseed(seed)
seeds[pid] = seed
end
local function randomseed()
local seed = get_seed_from_urandom()
if not seed then
ngx.log(ngx.WARN, 'failed to get seed from urandom')
seed = ngx.now() * 1000 + ngx.worker.pid()
end
math.randomseed(seed)
end
local function redirect_to_https()
return ngx.var.pass_access_scheme == "http" and (ngx.var.scheme == "http" or ngx.var.scheme == "https")
end
local function redirect_host()
local host_port, err = ngx_re_split(ngx.var.best_http_host, ":")
if err then
ngx.log(ngx.ERR, "could not parse variable: ", err)
return ngx.var.best_http_host;
end
return host_port[1];
end
local function parse_x_forwarded_host()
local hosts, err = ngx_re_split(ngx.var.http_x_forwarded_host, ",")
if err then
ngx.log(ngx.ERR, string_format("could not parse variable: %s", err))
return ""
end
return hosts[1]
end
function _M.init_worker()
randomseed()
end
function _M.set_config(new_config)
config = new_config
end
-- rewrite gets called in every location context.
-- This is where we do variable assignments to be used in subsequent
-- phases or redirection
function _M.rewrite(location_config)
ngx.var.pass_access_scheme = ngx.var.scheme
ngx.var.pass_server_port = ngx.var.server_port
ngx.var.best_http_host = ngx.var.http_host or ngx.var.host
if config.use_forwarded_headers then
-- trust http_x_forwarded_proto headers correctly indicate ssl offloading
if ngx.var.http_x_forwarded_proto then
ngx.var.pass_access_scheme = ngx.var.http_x_forwarded_proto
end
if ngx.var.http_x_forwarded_port then
ngx.var.pass_server_port = ngx.var.http_x_forwarded_port
end
-- Obtain best http host
if ngx.var.http_x_forwarded_host then
ngx.var.best_http_host = parse_x_forwarded_host()
end
end
ngx.var.pass_port = ngx.var.pass_server_port
if config.is_ssl_passthrough_enabled then
if ngx.var.pass_server_port == config.listen_ports.ssl_proxy then
ngx.var.pass_port = 443
end
elseif ngx.var.pass_server_port == config.listen_ports.https then
ngx.var.pass_port = 443
end
if location_config.force_ssl_redirect and redirect_to_https() then
local uri = string_format("https://%s%s", redirect_host(), ngx.var.request_uri)
if location_config.use_port_in_redirects then
uri = string_format("https://%s:%s%s", redirect_host(), config.listen_ports.https, ngx.var.request_uri)
end
ngx_redirect(uri, config.http_redirect_code)
end
end
return _M