Bug 868391

Summary: xl2tpd sends response packets from wrong IP address
Product: [Fedora] Fedora EPEL Reporter: James Moore <jtmoore>
Component: xl2tpdAssignee: Paul Wouters <pwouters>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: high Docs Contact:
Priority: unspecified    
Version: el5CC: bbs2web, pwouters, timur
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: xl2tpd-1.3.6-1.el6 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-05-21 23:27:23 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description James Moore 2012-10-19 17:29:10 UTC
When xl2tpd Version 1.3.1 Release 1.el5 is installed on a system with multiple network interfaces, XL2TPD always sends response packets with the source IP address set to the address of the interface that the packet leaves from unless xl2tpd is bound to a single IP address with the listen-addr directive in xl2tpd.conf. This is not the correct behavior and makes it impossible to configure xl2tpd to listen on multiple ip addresses when asymmetric routing may occur. See the diagram below:

       |----------------INTERNET----------------|
     ISP-A                                    ISP-B
       |                                       |
       |                                       |
    (eth3)                                   (eth3)
 Linux Router A-(eth2)-----------(eth2)-Linux Router B
    (eth1)                                   (eth1)
       |                                         |
       |(-----------------VRRP------------------)|
       |                                         |
       ------------------Switches-----------------
                           |
                       DMZ Network


Linux Router A and Linux Router B run BGP with the connected ISP and each other. Depending on current networking conditions and BGP configurations, response packets may be sent out a different interface and ISP than the incoming packets are received on. Unless xl2tpd is bound to a single IP address with the listen-addr directive in xl2tpd.conf, xl2tpd incorrectly sends response packets from the IP address of the interface the packet leaves from which in some cases may be different than the IP address that the L2TP/IPsec client tries to connects to. When this occurs, two problems occur: 1) The response packet is not encapsulated in IPsec and 2) even it it were possible to encrypt the packet, the client would not recognize the packet as belonging to the connection it was trying to establish.  For example, if an internet client tries to establish a L2TP/IPSec connection using the hostname or IP address assigned to the eth1 interface of either Linux router, the response packets from xl2tpd will use the IP address of either eth2 or eth3 unless xl2tpd is bound to the IP address assigned to eth1.

Under many circumstances binding XL2TPD to the IP address of the eth1 interface on each router would resolve the issue. However in my case, Linux Router A and Linux Router B also use VRRP to provide a highly available virtual gateway for the servers in the DMZ network. The MAC and IP addresses of the VRRP interface are only available on one of the routers at any given time. If the router currently holding the VRRP interface dies the other router seizes the MAC an IP addresses of the interface. Under ideal circumstances, I would want to allow XL2TPD to listen on all interfaces so that L2TP/IPsec clients could be configured to connect to hostname assigned to the VRRP interface to provide high availability. Unfortunately, I this can't be done if XL2TPD has to be bound to a single IP since the desired IP address to bind to will not be available on the backup VRRP router for binding until after a failure of the primary VRRP router occurs. 

On system running Linux kernels that lack IPsec Mast support (RedHat, Fedora, etc.), its also not possible to DNAT IPsec packets sent to the VRRP IP address to the eth1 IP address where XL2TPD is bound since the "unnatting" process occurs after the decision is made for whether or not to encapsulate the packet in IPSec so the response packets will not be encrypted when a DNAT is used.

I have attempted to contact the upstream development team using the email address listed in xl2tpd man pages (xl2tpd-dev) but the message bounced saying that the mailbox did not exist.

Comment 1 Paul Wouters 2012-10-19 22:22:05 UTC
I'll look into this.

I think it would be good enough for you if xl2tpd answers using the ip it was contacted at. Is that correct?

Paul

Comment 2 James Moore 2012-10-20 06:14:18 UTC
Yes, you are correct. I just need the response to always come from the same ip that was contacted without having to specify the listen-addr in the config. Thanks for for looking into it.

Comment 3 David Herselman 2012-11-22 22:15:29 UTC
This problem is common to most stateless connections utilising UDP. It would be great if Paul could submit a patch to get xl2tpd to simply originate responses using the same IPs that requests arrived on.

I am currently over coming this problem by logging connection requests and running a simple script every 2 minutes to add routing rules, which then results in the kernel sending UDP response packets using that device's IP address. The original purpose was to handle multiple concurrent SIP (VoIP) registrations on a multihomed system but it also works on L2TP tunnels.

NB: This can not handle multiple concurrent connections on a multi homed systems where the originating IP is the same.

Firewall rule:
iptables -A INPUT -m state --state NEW -p udp --dport 1701 -j LOG --log-prefix "routeme:"
iptables -A INPUT -m state --state NEW -p udp --dport 1701 -j ACCEPT

/etc/cron.2minutes/udp-router
#!/bin/sh
set_route () {
  [ "$dev" == "" ] && return;
  [ `echo $ip | grep -Pc '^\d{1,3}(\.\d{1,3}){3}$'` -lt 1 ] && return;
  [ `route -n | grep "^$ip" | grep -cv "$dev$"` -gt 0 ] && route del -host $ip;
  route add -host $ip dev $dev 2> /dev/null;
}

# Find firewall log entries that match 'routeme:' and add a route via the last interface:
ips=`tail -n 10000 /var/log/messages | grep 'routeme:' | perl -pe 's/.*SRC=(\d{1,3}(\.\d{1,3}){3}).*/\1/' | sort | uniq`;
for ip in $ips; do
  dev=(`tail -n 10000 /var/log/messages | grep "routeme:.*SRC=$ip" | perl -pe 's/.*IN=(\S+).*/\1/' | tail -n 1`;
  set_route;
done

Comment 4 James Moore 2012-11-26 13:59:32 UTC
David, that's an interesting approach. I'm surprised it works though. How do the firewall and application on the other side of the connection recognize the response from a different ip address?

Comment 5 James Moore 2012-11-26 14:03:57 UTC
David, I get it now, it forces the packet out the interface with the ip that the connection arrived on. This probably wouldn't work with IPSec in netkey mode though since the kernel wouldn't know that the packet belonged to an IPSec connection.

Comment 6 Paul Wouters 2012-11-28 04:35:12 UTC
I've started work on portinf his to recvfrom() recvfromto()

Comment 7 Timur Bakeyev 2014-05-12 15:00:02 UTC
I hit the same problem with xl2tpd 1.3.1 on Debian and was wondering - was there any progress on this bug?

It seems, that development of xl2tpd now moved to https://github.com/xelerance/xl2tpd

Comment 8 Fedora Update System 2014-05-13 15:36:51 UTC
xl2tpd-1.3.6-1.fc20 has been submitted as an update for Fedora 20.
https://admin.fedoraproject.org/updates/xl2tpd-1.3.6-1.fc20

Comment 9 Fedora Update System 2014-05-13 15:38:49 UTC
xl2tpd-1.3.6-1.fc19 has been submitted as an update for Fedora 19.
https://admin.fedoraproject.org/updates/xl2tpd-1.3.6-1.fc19

Comment 10 Fedora Update System 2014-05-13 15:39:57 UTC
xl2tpd-1.3.6-1.el6 has been submitted as an update for Fedora EPEL 6.
https://admin.fedoraproject.org/updates/xl2tpd-1.3.6-1.el6

Comment 11 Fedora Update System 2014-05-14 23:55:23 UTC
Package xl2tpd-1.3.6-1.fc19:
* should fix your issue,
* was pushed to the Fedora 19 testing repository,
* should be available at your local mirror within two days.
Update it with:
# su -c 'yum update --enablerepo=updates-testing xl2tpd-1.3.6-1.fc19'
as soon as you are able to.
Please go to the following url:
https://admin.fedoraproject.org/updates/FEDORA-2014-6347/xl2tpd-1.3.6-1.fc19
then log in and leave karma (feedback).

Comment 12 Fedora Update System 2014-05-21 23:27:23 UTC
xl2tpd-1.3.6-1.fc20 has been pushed to the Fedora 20 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 13 Fedora Update System 2014-05-24 23:24:29 UTC
xl2tpd-1.3.6-1.fc19 has been pushed to the Fedora 19 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 14 Fedora Update System 2014-05-31 18:35:50 UTC
xl2tpd-1.3.6-1.el6 has been pushed to the Fedora EPEL 6 stable repository.  If problems still persist, please make note of it in this bug report.