Hi Pablo,

Thank you for getting back to me. Also thanks for pointing me to
libnetfilter_conntrack, I will definitely have a look.

I am using kernel 4.1.39 and the issue can be reproduced with the following ruleset on the Proxy host:

iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
ip rule add fwmark 1 lookup 100
ip route add local dev lo table 100
iptables -t mangle -A PREROUTING -p tcp ! --dport 21 -i eth0 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 9999

Then I simply retrieve an FTP file (in passive mode) from the client and I use a toy C program (see below) on the Proxy to retrieve the source IP.

I am still wondering if the IP returned by accept is a normal behavior. What do you think? Don't we expect accept() to return the client's IP?


#include <stdio.h>
#include <arpa/inet.h>
int main()
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        int sock;
        int one = 1;

        addr.sin_family = AF_INET;
        addr.sin_port = htons(9999);
        addr.sin_addr.s_addr = INADDR_ANY;

        sock = socket(PF_INET, SOCK_STREAM, 0);
        setsockopt(sock, SOL_IP, IP_TRANSPARENT, &one, sizeof(one));
        bind(sock, (struct sockaddr*)&addr, sizeof(addr));
        listen(sock, 1);
        accept(sock,(struct sockaddr *)&addr, &len);

        char *ip = inet_ntoa(addr.sin_addr);
        printf("%s\n", ip);

On 02/08/2018 05:55 PM, Pablo Neira Ayuso wrote:
Hi Gregory,

On Tue, Feb 06, 2018 at 03:40:20PM +0100, Gregory Vander Schueren wrote:

I have the following IPv4 network:

FTPClient <-----------------> Proxy <--------------> FTPServer.

FTPClient connects to FTPServer in PASSIVE mode, meaning the FTPClient
initiates the data connection towards FTPServer. Proxy performs NAT in the
POSTROUTING chain using the iptables MASQUERADE target. On Proxy, I use the
iptables TPROXY target to redirect the FTP data connection towards a local

Upon accept() on this socket, the address returned by accept() is,
not the IP of the Client ( as I expected. Using getpeername() also
returns For other TCP connections than FTP accept() or
getpeername() returns

I noticed this only occurs when using the NF_CONNTRACK_FTP and NF_NAT_FTP
kernel modules.

Note that I was able to retrieve the FTPClient IP on Proxy from
/proc/net/ip_conntrack. I also made a quick patch to add a SO_ORIGINAL_SRC 
socket option
(similar to SO_ORIGINAL_DST) which allows to retrieve the FTPClient
IP. Since this option does not exist yet, I am wondering if this is
relevant to add such an option?

You can use libnetfilter_conntrack to do this these days, via ctnetlink.

Also, this does not occur in IPv6.

Is this behavior normal?

Probably it is related to your ruleset? You could post an example to
reproduce the issue and your kernel version.



This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to