CloudFlare was gracious enough to open source a Lua function to convert IPv6 addresses into pseudo IPv4 addresses using the Class E addressesing space.
The class E block of addresses are reserved and cannot be used for external routed devices, so we know there won’t be an overlap with existing IPv4 users.
http {
...
init_by_lua '
function pseudo_ipv4(ip)
-- check for format 1.11.111.111 for ipv4
local chunks = {ip:match("(%d+)%.(%d+)%.(%d+)%.(%d+)")}
if (#chunks == 4) then
for _,v in pairs(chunks) do
if (tonumber(v) < 0 or tonumber(v) > 255) then
return 0
end
end
return ip
else
-- Grab bottom 32 bits from MD5 hash
local md5 = ngx.md5_bin(ip)
local b1, b2, b3, b4 = md5:byte(13, 16)
-- Normalize first byte to fit in class E space
b1 = bit.bor(0xF0, bit.band(b1, 0x0F))
return string.format("%d.%d.%d.%d", b1, b2, b3, b4)
end
end
';
server {
listen [::]:80;
listen 80;
...
location / {
default_type text/html;
set_by_lua $pseudo_ip "return pseudo_ipv4(ngx.var.remote_addr)";
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Connecting-IPv6 $pseudo_ip;
proxy_redirect off;
proxy_connect_timeout 10;
proxy_send_timeout 30;
proxy_read_timeout 30;
proxy_pass http://backend;
}
...
}