[squid-users] FTP relay with active client is broken?
Alex
gozzy at yandex.ru
Mon Feb 13 12:18:59 UTC 2017
Well, actually it looks like a bug in squid to me. Some points:
1. When client connects with active FTP mode, squid opens a local socket and tries to assign server's IP address to it. So far so good, however this doesn't work (tested in both 'intercept' and 'tproxy' modes):
2017/02/13 14:58:51.234| 50,3| comm.cc(347) comm_openex: comm_openex: Attempt open socket for: 172.17.10.30
2017/02/13 14:58:51.234| 50,3| comm.cc(388) comm_openex: comm_openex: Opened socket local=172.17.10.30 remote=[::] FD 17 flags=1 : family=2, type=1, protocol=6
2017/02/13 14:58:51.234| 5,5| comm.cc(420) comm_init_opened: local=172.17.10.30 remote=[::] FD 17 flags=1 is a new socket
2017/02/13 14:58:51.234| 51,3| fd.cc(198) fd_open: fd_open() FD 17
2017/02/13 14:58:51.234| commBind: Cannot bind socket FD 17 to 172.17.10.30: (99) Cannot assign requested address
2. Ok, we've got the errno. Let's look in comm_apply_flags(). There's something like this in the middle:
/* MUST be done before binding or face OS Error: "(99) Cannot assign requested address"... */
if ((flags & COMM_TRANSPARENT)) {
comm_set_transparent(new_socket);
}
This means that socket is not IP_TRANSPARENT and can not be bound to arbitrary IP address ('net.ipv4.ip_nonlocal_bind' can fix bind(), but connect() will obviously fail with EINVAL).
3. Let's take a look on Ftp::Server::createDataConnection():
Comm::ConnectionPointer conn = new Comm::Connection();
conn->flags |= COMM_DOBIND;
// Use local IP address of the control connection as the source address
// of the active data connection, or some clients will refuse to accept.
conn->setAddrs(clientConnection->local, cltAddr);
Fine, looks reasonable. However, connection has only COMM_DOBIND flag, COMM_TRANSPARENT is missing. AFAIU, we'll never be able to bind and connect a socket...
4. Finally, in restoreCapabilities():
if (Ip::Interceptor.TransparentActive() ||
Ip::Qos::TheConfig.isHitNfmarkActive() ||
Ip::Qos::TheConfig.isAclNfmarkActive() ||
Ip::Qos::TheConfig.isAclTosActive()) {
cap_list[ncaps] = CAP_NET_ADMIN;
++ncaps;
}
Hmm... Looks like that spoofing will not work for any mode other than 'tproxy', because there's no InterceptActive() check. But anyway, without COMM_TRANSPARENT it's useless.
To sum up, I see some possible mistakes that may cause bugs in FTP relaying. I realise that probably I do something wrong also, however due to lack of documentation for FTP relay there's no simple way to check this :)
08.02.2017, 19:11, "Alex Rousskov" <rousskov at measurement-factory.com>:
> On 02/08/2017 06:10 AM, Alex wrote:
>
>> I've specified
>> 'ftp_port 2121 intercept' and made squid intercept outgoing FTP
>> traffic according to the following rules:
>
>> iptables -t nat -A OUTPUT -p tcp -m owner --gid-owner squid -j ACCEPT
>> iptables -t nat -A OUTPUT -p tcp --dport 21 -j REDIRECT --to-port 2121
>
>> 07.02.2017, 16:23, "Alex" <gozzy at yandex.ru>:
>
>>> I thought that active mode will cause less problems, but it seems
>>> that what squid tries to do is illegal. As far as I understand, in
>>> active mode squid tries to connect to a client and spoofs source IP
>>> address.
>
> Since spoofing client IP addresses is common for many working Squid
> interception setups doing HTTP, it has to be technically possible (i.e.,
> "legal" in your terminology). Unfortunately, I do not know enough
> low-level details to guide you further. Most likely, the FTP-specific
> Squid code facilitating IP spoofing is buggy or you are doing something
> wrong (or both).
>
> FWIW, IIRC, FTP interception code has worked for many folks.
>
> Let's hope that somebody with a working FTP interception setup speaks up.
>
> Alex.
More information about the squid-users
mailing list