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


OpenResty CentOS 7 Systemd Script

I’ve been slowly getting adjusted to systemd on CentOS 7. OpenResty has been gaining in popularity and I was interested in getting a proper build for CentOS 7.

Below is my systemd service file for OpenResty/nginx, this is based on the default install path /usr/local/openresty Filename: /usr/lib/systemd/system/nginx.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=The nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/openresty/nginx/logs/nginx.pid
ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t
ExecStart=/usr/local/openresty/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Then to enable and start the new service

1
2
systemctl enable nginx.service
systemctl start nginx.service

This post may evolve as I work on building an RPM for OpenResty based on the EPEL nginx SRPM package. I should note the majority of the service file above is from the EPEL nginx package.


Other handy oneliners

  • Top IP addresses in Apache access_log tail -10000 access_log | awk '{print $1}' | sort | uniq -c | sort -n | tail

  • Top IPs from netstat netstat -tn 2>/dev/null | grep :80 | awk '{print $5}' |sed -e 's/::ffff://' |cut -d: -f1 | sort | uniq -c | sort -rn |head

  • Capture sterr/stout from specified PID strace -ff -e trace=write -e write=1,2 -p PID