Mar 11 06:48:15 myserver xinetd: START: ftp pid=4721 from=22.214.171.124
Mar 11 06:48:15 myserver xinetd: libwrap refused connection to ftp (libwrap=vsftpd) from 126.96.36.199
Mar 11 06:48:15 myserver xinetd: FAIL: ftp libwrap from=188.8.131.52
Mar 11 06:48:15 myserver xinetd: EXIT: ftp status=0 pid=4721 duration=0(sec)
I believe this is a rererse lookup failure. When I dig the client hostname from the server I get the right IP (in my example 184.108.40.206). But when I reverse the dig (dig -x 220.127.116.11) I get the hostname of the client's ISP, which is logical. libwrap fools vsftpd into balieving this is a spoofed hostname, and so rejects the connection.
When I put the IP 18.104.22.168 into hosts.allow, vsftpd accepts the connection.
Just to clarify: When I said "dynamic IP" in my first post I did not mean "private (eg 192.168.x.x), I meant it as an address allocated dynamically by the ISP each time the client's computer boots. The address is public, it just isn't the same accross boots.