Pseudo IPv4 addresses for IPv6 users - OpenResty

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.

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
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;

        }

...

}

Reference: http://blog.cloudflare.com/eliminating-the-last-reasons-to-not-enable-ipv6/ http://stackoverflow.com/questions/10975935/lua-function-check-if-ipv4-or-ipv6-or-string http://wiki.nginx.org/HttpLuaModule#ngx.send_headers https://github.com/octohost/openresty