gluon-status-page: when visiting via a next-node address, redirect to a unique address
A downside of this behaviour is that the page does not work for IPv4-only clients, as the redirect will always point at an IPv6 address. Still, it seems like a good idea to enforce the redirect even from the IPv4 next-node address, as switching nodes while being connected to the status page would lead to unexpected behaviour.
This commit is contained in:
		
							parent
							
								
									fdf823a3a2
								
							
						
					
					
						commit
						27f7ce444f
					
				| @ -1,6 +1,5 @@ | ||||
| <%- | ||||
| 	local fs = require 'nixio.fs' | ||||
| 	local json = require 'jsonc' | ||||
| 	local ubus = require 'ubus' | ||||
| 	local util = require 'gluon.util' | ||||
| 
 | ||||
| @ -44,8 +43,6 @@ | ||||
| 
 | ||||
| 	local interfaces = get_interfaces() | ||||
| 
 | ||||
| 	local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 1 -c 1 -r nodeinfo')) | ||||
| 
 | ||||
| 	local function sorted(t) | ||||
| 		t = {unpack(t)} | ||||
| 		table.sort(t) | ||||
|  | ||||
| @ -1,3 +1,87 @@ | ||||
| local json = require 'jsonc' | ||||
| local site = require 'gluon.site' | ||||
| local util = require 'gluon.util' | ||||
| 
 | ||||
| local function parse_ip(addr) | ||||
| 	if not addr then return end | ||||
| 
 | ||||
| 	local ip4 = {addr:match('(%d+)%.(%d+)%.(%d+)%.(%d+)')} | ||||
| 	if ip4[1] then | ||||
| 		local ret = {} | ||||
| 
 | ||||
| 		for i, part in ipairs(ip4) do | ||||
| 			ret[i] = tonumber(part) | ||||
| 		end | ||||
| 		return ret | ||||
| 	end | ||||
| 
 | ||||
| 	if not addr:match('^[:%x]+$') then | ||||
| 		return | ||||
| 	end | ||||
| 
 | ||||
| 	if addr:sub(0, 2) == '::' then | ||||
| 		addr = '0' .. addr | ||||
| 	end | ||||
| 	if addr:sub(-2) == '::' then | ||||
| 		addr = addr .. '0' | ||||
| 	end | ||||
| 
 | ||||
| 	addr = addr .. ':' | ||||
| 
 | ||||
| 	local groups, groups1 = {}, {} | ||||
| 	for part in addr:gmatch('([^:]*):') do | ||||
| 		if part == '' then | ||||
| 			groups1 = groups | ||||
| 			groups = {} | ||||
| 		else | ||||
| 			groups[#groups+1] = tonumber(part, 16) | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	while #groups + #groups1 < 8 do | ||||
| 		groups1[#groups1+1] = 0 | ||||
| 	end | ||||
| 	for _, group in ipairs(groups) do | ||||
| 		groups1[#groups1+1] = group | ||||
| 	end | ||||
| 
 | ||||
| 	return groups1 | ||||
| end | ||||
| 
 | ||||
| local function match(a, b, n) | ||||
| 	if not a or not b then return false end | ||||
| 
 | ||||
| 	for i = 1, n do | ||||
| 		if a[i] ~= b[i] then | ||||
| 			return false | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	return true | ||||
| end | ||||
| 
 | ||||
| entry({}, call(function(http, renderer) | ||||
| 	renderer.render('status-page', nil, 'gluon-status-page') | ||||
| 	local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 1 -c 1 -r nodeinfo')) | ||||
| 
 | ||||
| 	local node_ip = parse_ip(http:getenv('SERVER_ADDR')) | ||||
| 	if node_ip and ( | ||||
| 			match(node_ip, parse_ip(site.next_node.ip4()), 8) or | ||||
| 			match(node_ip, parse_ip(site.next_node.ip6()), 8) | ||||
| 	) then | ||||
| 		-- The user has visited the status page via a next-node address | ||||
| 		-- Redirect the user the a unique address to avoid switching | ||||
| 		-- nodes | ||||
| 		local prefix = parse_ip(site.prefix6():match('^[^/]+')) | ||||
| 		for _, addr in ipairs(nodeinfo.network.addresses) do | ||||
| 			if match(prefix, parse_ip(addr), 4) then | ||||
| 				http:header('Cache-Control', 'no-cache, no-store, must-revalidate') | ||||
| 				http:redirect('http://[' .. addr .. ']' .. http:getenv('REQUEST_URI')) | ||||
| 				http:close() | ||||
| 				return | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 
 | ||||
| 	renderer.render('status-page', { nodeinfo = nodeinfo }, 'gluon-status-page') | ||||
| end)) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user