Bug 192888 - ipfw NAT vulnerable to simple DOS attacks
Summary: ipfw NAT vulnerable to simple DOS attacks
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 9.2-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: Lutz Donnerhacke
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-08-21 13:57 UTC by napTu
Modified: 2021-07-06 07:20 UTC (History)
3 users (show)

See Also:
donner: mfc-stable13+
donner: mfc-stable12+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description napTu 2014-08-21 13:57:22 UTC
ipfw NAT vulnerable to DOS attacks by sending ip packets to external ip address and any port.
In this situation CPU usage goes to 100%.

NAT should find a matched internal address, and, if not, skip the packet to external ip.

This process (with failed search) take a many time and resources.
Comment 1 Tom Jones freebsd_committer freebsd_triage 2020-09-19 16:35:58 UTC
Could you add some more detail or steps to reproduce? If this issue still exists in FreeBSD I would be very interested in fixing this. If I don't have any response in the next few months I will close this issue.
Comment 2 Lutz Donnerhacke freebsd_committer freebsd_triage 2020-09-20 11:26:08 UTC
It seems that the problems still exists:
(Articles in German)
https://lutz.donnerhacke.de/Blog/Performance-Probleme-mit-NAT
https://lutz.donnerhacke.de/Blog/Wenn-der-Traceroute-Kreise-tanzt

It's a variant of the LAND attack https://en.wikipedia.org/wiki/LAND.

My solution is to use ipfw (which is used to activate NAT) to drop incoming packets sourced from the public NAT IP. So simple antispoofing.
Comment 3 Lutz Donnerhacke freebsd_committer freebsd_triage 2021-05-02 20:09:01 UTC
All versions up to current are affected.
Comment 4 Lutz Donnerhacke freebsd_committer freebsd_triage 2021-05-04 16:24:29 UTC
I went through the source code and can drill the problem down to an full scan of an unsorted linked list in a given hash bucket. This eats CPU cycles for breakfast.

A workaround is to increase the hash table size in sys/netinet/libalias/alias_local.h:
#define LINK_TABLE_OUT_SIZE        4001

A short term solution is to make the hard coded parameters tunable.

But the real solution is to find a data structure which allows sub linear access methods to the flow data. Possibly using a non blocking algorithm for access and modification.
Comment 5 Lutz Donnerhacke freebsd_committer freebsd_triage 2021-05-20 06:28:54 UTC
Work towards a solution in review D30259, review D30277, review D30283, review D30307, and review D30335
Comment 6 Lutz Donnerhacke freebsd_committer freebsd_triage 2021-06-04 10:48:51 UTC
May you try to apply those patches, please?

https://reviews.freebsd.org/D30516
https://reviews.freebsd.org/D30536
Comment 7 commit-hook freebsd_committer freebsd_triage 2021-06-19 20:28:45 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=d261e57deacb0d00d9e827447f235df83dda3e3a

commit d261e57deacb0d00d9e827447f235df83dda3e3a
Author:     Lutz Donnerhacke <donner@FreeBSD.org>
AuthorDate: 2021-05-28 20:36:59 +0000
Commit:     Lutz Donnerhacke <donner@FreeBSD.org>
CommitDate: 2021-06-19 20:12:28 +0000

    libalias: Switch to efficient data structure for incoming traffic

    Current data structure is using a hash of unordered lists.  Those
    unordered lists are quite efficient, because the least recently
    inserted entries are most likely to be used again.  In order to avoid
    long search times in other cases, the lists are hashed into many
    buckets.  Unfortunatly a search for a miss needs an exhaustive
    inspection and a careful definition of the hash.

    Splay trees offer a similar feature: Almost O(1) for access of the
    least recently used entries, and amortized O(ln(n)) for almost all
    other cases.  Get rid of the hash.

    Now the data structure should able to quickly react to external
    packets without eating CPU cycles for breakfast, preventing a DoS.

    PR:             192888
    Discussed with: Dimitry Luhtionov
    MFC after:      1 week
    Differential Revision: https://reviews.freebsd.org/D30536

 sys/netinet/libalias/alias_db.c    | 75 +++++++++++++++++---------------------
 sys/netinet/libalias/alias_local.h |  6 +--
 2 files changed, 36 insertions(+), 45 deletions(-)
Comment 8 Lutz Donnerhacke freebsd_committer freebsd_triage 2021-06-19 20:31:59 UTC
May you please test your problem against 14-CURRENT?
Comment 9 commit-hook freebsd_committer freebsd_triage 2021-07-06 06:56:43 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=3a96a25da8614d27f717ba8d29d32bafb04a70e8

commit 3a96a25da8614d27f717ba8d29d32bafb04a70e8
Author:     Lutz Donnerhacke <donner@FreeBSD.org>
AuthorDate: 2021-05-27 21:42:54 +0000
Commit:     Lutz Donnerhacke <donner@FreeBSD.org>
CommitDate: 2021-07-06 06:55:53 +0000

    libalias: Switch to SPLAY trees

    Current data structure is using a hash of unordered lists.  Those
    unordered lists are quite efficient, because the least recently
    inserted entries are most likely to be used again.  In order to avoid
    long search times in other cases, the lists are hashed into many
    buckets.  Unfortunatly a search for a miss needs an exhaustive
    inspection and a careful definition of the hash.

    Splay trees offer a similar feature - almost O(1) for access of the
    least recently used entries), and amortized O(ln(n) - for almost all
    other cases.  Get rid of the hash.

    Now the data structure should able to quickly react to external
    packets without eating CPU cycles for breakfast, preventing a DoS.

    PR:             192888
    Discussed with: Dimitry Luhtionov
    Differential Revision: https://reviews.freebsd.org/D30516
    Differential Revision: https://reviews.freebsd.org/D30536
    Differential Revision: https://reviews.freebsd.org/D30844

    (cherry picked from commit 935fc93af157dee352eb4b6c83f8a2a9e7fd9a4e)
    (cherry picked from commit d261e57deacb0d00d9e827447f235df83dda3e3a)
    (cherry picked from commit f70c98a2f5d993dc518efd606aa341eda99400ef)
    (cherry picked from commit 25392fac9488bcae5c451500df2e2945430484a6)
    (cherry picked from commit 2f4d91f9cb22fc65eb65407e8118b433a5d71976)
    (cherry picked from commit 4060e77f49d1b9fd2254f3f4da94fd64fce83f72)

 sys/netinet/libalias/HISTORY          |   3 +-
 sys/netinet/libalias/alias_db.c       | 502 +++-------------------------------
 sys/netinet/libalias/alias_db.h (new) | 443 ++++++++++++++++++++++++++++++
 sys/netinet/libalias/alias_local.h    |  10 +-
 4 files changed, 489 insertions(+), 469 deletions(-)
Comment 10 commit-hook freebsd_committer freebsd_triage 2021-07-06 07:12:48 UTC
A commit in branch stable/12 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=1883127de4888b2a30a6cb51e8fb4bdf33b7f411

commit 1883127de4888b2a30a6cb51e8fb4bdf33b7f411
Author:     Lutz Donnerhacke <donner@FreeBSD.org>
AuthorDate: 2021-05-27 21:42:54 +0000
Commit:     Lutz Donnerhacke <donner@FreeBSD.org>
CommitDate: 2021-07-06 07:10:02 +0000

    libalias: Switch to SPLAY trees

    Current data structure is using a hash of unordered lists.  Those
    unordered lists are quite efficient, because the least recently
    inserted entries are most likely to be used again.  In order to avoid
    long search times in other cases, the lists are hashed into many
    buckets.  Unfortunatly a search for a miss needs an exhaustive
    inspection and a careful definition of the hash.

    Splay trees offer a similar feature - almost O(1) for access of the
    least recently used entries), and amortized O(ln(n) - for almost all
    other cases.  Get rid of the hash.

    Now the data structure should able to quickly react to external
    packets without eating CPU cycles for breakfast, preventing a DoS.

    PR:             192888
    Discussed with: Dimitry Luhtionov
    Differential Revision: https://reviews.freebsd.org/D30516
    Differential Revision: https://reviews.freebsd.org/D30536
    Differential Revision: https://reviews.freebsd.org/D30844

    (cherry picked from commit 935fc93af157dee352eb4b6c83f8a2a9e7fd9a4e)
    (cherry picked from commit d261e57deacb0d00d9e827447f235df83dda3e3a)
    (cherry picked from commit f70c98a2f5d993dc518efd606aa341eda99400ef)
    (cherry picked from commit 25392fac9488bcae5c451500df2e2945430484a6)
    (cherry picked from commit 2f4d91f9cb22fc65eb65407e8118b433a5d71976)
    (cherry picked from commit 4060e77f49d1b9fd2254f3f4da94fd64fce83f72)

 sys/netinet/libalias/HISTORY          |   3 +-
 sys/netinet/libalias/alias_db.c       | 502 +++-------------------------------
 sys/netinet/libalias/alias_db.h (new) | 443 ++++++++++++++++++++++++++++++
 sys/netinet/libalias/alias_local.h    |  10 +-
 4 files changed, 489 insertions(+), 469 deletions(-)
Comment 11 Lutz Donnerhacke freebsd_committer freebsd_triage 2021-07-06 07:20:19 UTC
Seems to be solved.
Hopefully.