溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何進(jìn)行Linux Netfilter調(diào)優(yōu)

發(fā)布時(shí)間:2021-10-22 11:23:04 來源:億速云 閱讀:453 作者:柒染 欄目:云計(jì)算

這篇文章將為大家詳細(xì)講解有關(guān)如何進(jìn)行Linux Netfilter調(diào)優(yōu),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

如果您正在為高流量的 Web/DNS 服務(wù)器提供服務(wù),并且最近使該服務(wù)器 PING 丟失并且并非所有 HTTP 請(qǐng)求都成功。您可以開始檢查系統(tǒng)日志。并且如果您看到類似下面的內(nèi)容,那么下面的指南將幫助您調(diào)整 Linux 服務(wù)器以正確處理流量負(fù)載。

Mar 22 21:25:55 localhost kernel: nf_conntrack: table full, dropping packet.
Mar 22 21:26:00 localhost kernel: printk: 11 messages suppressed.
Mar 22 21:26:00 localhost kernel: nf_conntrack: table full, dropping packet.
Mar 22 21:26:05 localhost kernel: printk: 16 messages suppressed.

狀態(tài)查看

  • buckets 哈希表大小,max 最大記錄的連接條數(shù)

    sudo dmesg | grep conntrack

    [    8.782060] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
  • 哈希表使用情況

    grep conntrack /proc/slabinfo

    nf_conntrack_1       102    102    320   51    4 : tunables    0    0    0 : slabdata      2      2      0
  • 當(dāng)前跟蹤的連接數(shù)

    sudo sysctl net.netfilter.nf_conntrack_count
  • 跟蹤連接詳細(xì)信息

    # centos
    cat /proc/net/nf_conntrack
    # ubuntu,可能需要安裝 conntrack 工具,yum install -y conntrack 或者 apt-getinstall -y conntrack
    conntrack -L

    最大連接跟蹤數(shù)

為了完成任務(wù),NAT-server(一般指的是 iptables) 需要記錄所有通過它的連接。無(wú)論是 “ping” 還是某人的 “ICQ”,NAT-server 都會(huì)記錄在一個(gè)特殊的表中并跟蹤所有會(huì)話。當(dāng)會(huì)話關(guān)閉時(shí),相關(guān)記錄將從連接跟蹤表中刪除。這個(gè)記錄表的大小是固定的,所以如果通過服務(wù)器的流量很大,但表太小,那么 NAT-server 就會(huì)開始丟棄數(shù)據(jù)包,中斷會(huì)話。為了避免這樣的麻煩,有必要適當(dāng)增加連接跟蹤表的大小。

  • 最大連接跟蹤數(shù)默認(rèn)為 *nf_conntrack_buckets * 4*,可以通過以下命令查看當(dāng)前值:

    sysctl net.netfilter.nf_conntrack_buckets
    sysctl net.netfilter.nf_conntrack_max
  • CONNTRACK_MAX 默認(rèn)計(jì)算公式

    CONNTRACK_MAX = 內(nèi)存?zhèn)€數(shù)*1024*1024*1024/16384/(ARCH/32)
    • 其中 ARCH 為 CPU 架構(gòu),值為 32 或 64。

    • 比如:64 位 8G 內(nèi)存的機(jī)器:(8*1024^3)/16384/(64/32) = 262144

臨時(shí)調(diào)整

臨時(shí)調(diào)整是臨時(shí)性的,重啟節(jié)點(diǎn)好配置值將會(huì)丟失。

sysctl -w net.netfilter.nf_conntrack_max=1048576
sysctl -w net.nf_conntrack_max=1048576

永久調(diào)整

要使其配置在重新啟動(dòng)后永久存在,需要將這些值添加到 sysctl.conf

echo 'net.netfilter.nf_conntrack_max' = 1048576 >> /etc/sysctl.conf
echo 'net.nf_conntrack_max = 1048576' >> /etc/sysctl.conf
sysctl  -p

如果服務(wù)器中的 RAM 少于 1 GB,建議不要設(shè)置太大的值。

哈希表(hash-table)

哈希表大小是只讀的,不能在 /etc/sysctl.conf 文件中設(shè)置值。64 位 Linux 系統(tǒng)中,4G 內(nèi)存默認(rèn) 16384,8G 內(nèi)存默認(rèn) 65536,16G 翻倍,以此類推。

給哈希表擴(kuò)容的影響

主要是內(nèi)存使用增加,32 位系統(tǒng)還要關(guān)心內(nèi)核態(tài)的地址空間夠不夠。

netfilter 的哈希表存儲(chǔ)在內(nèi)核態(tài)的內(nèi)存空間,這部分內(nèi)存不能 swap,操作系統(tǒng)為了兼容 32 位,默認(rèn)值往往比較保守。

  • 32 位系統(tǒng)的虛擬地址空間最多 4G,其中內(nèi)核態(tài)最多 1G,通常能用的只有前 896M。

    給 netfilter 分配太多地址空間可能會(huì)導(dǎo)致其他內(nèi)核進(jìn)程不夠分配。1 條跟蹤記錄 300 字節(jié)左右,因此當(dāng)年 nf_conntrack_max 默認(rèn) 65535 條,占 20 多 MB。

  • 64 位系統(tǒng)的虛擬地址空間有 256 TB,內(nèi)核態(tài)能用一半,只需要關(guān)心物理內(nèi)存的使用情況。

  • 計(jì)算內(nèi)存使用的公式

    size_of_mem_used_by_conntrack (in bytes) = CONNTRACK_MAX * sizeof(struct ip_conntrack) + HASHSIZE * sizeof(struct list_head)
    • sizeof(struct ip_conntrack) 在不同架構(gòu)、內(nèi)核版本、編譯選項(xiàng)下不一樣。這里按 352 字節(jié)算。

    • sizeof(struct list_head) = 2 * size_of_a_pointer(32 位系統(tǒng)的指針大小是 4 字節(jié),64 位是 8 字節(jié))

    • 64 位系統(tǒng),8G 內(nèi)存的機(jī)器,按默認(rèn) CONNTRACK_MAX 為 262144,HASHSIZE 為 65536 時(shí):262144 * 352 + 65536 * 8 = 92798976(88.5 MB)

  • 互聯(lián)網(wǎng)公司的服務(wù)器通常內(nèi)存沒那么緊張,可以放開點(diǎn):

    • CONNTRACK_MAX 為 1048576,HASHSIZE 為 262144 ,內(nèi)存大概使用:1048576 * 352 + 262144 * 8 = 371195904(354 MB)

哈希表大小調(diào)整

需要通過內(nèi)核模塊的方式修改:

  • 臨時(shí)生效:

    echo 262144 > /sys/module/nf_conntrack/parameters/hashsize
  • 永久生效

    將以下內(nèi)容添加到文件:/etc/modprobe.d/iptables.conf(如果沒有則新建)

    echo 'options nf_conntrack hashsize=262144' >> /etc/modprobe.d/iptables.conf

減少超時(shí)時(shí)間

NAT-server 只跟蹤通過它的 活動(dòng) 的會(huì)話。如果一個(gè)會(huì)話很長(zhǎng)時(shí)間是空閑的,不活躍,它將會(huì)因?yàn)槌刀魂P(guān)閉。當(dāng)會(huì)話關(guān)閉時(shí),關(guān)于它的信息將被刪除,以便連接跟蹤表不會(huì)溢出。

但是,如果超時(shí)的默認(rèn)值很大,流量較大時(shí)候,即使將 nf_conntrack_max 擴(kuò)展到了極限,跟蹤表仍然有溢出的風(fēng)險(xiǎn)。為此,必須在 NAT-server 上正確設(shè)置連接跟蹤超時(shí)。

可以執(zhí)行以下命令查看默認(rèn)值:

sysctl -a | grep conntrack | grep timeout

  • Ubuntu 16.04

    net.netfilter.nf_conntrack_generic_timeout = 600
    net.netfilter.nf_conntrack_icmp_timeout = 30
    net.netfilter.nf_conntrack_tcp_timeout_close = 10
    net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
    net.netfilter.nf_conntrack_tcp_timeout_established = 432000
    net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
    net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
    net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
    net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
    net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
    net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
    net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
    net.netfilter.nf_conntrack_udp_timeout = 30
    net.netfilter.nf_conntrack_udp_timeout_stream = 180
  • centos 7.8

    net.netfilter.nf_conntrack_dccp_timeout_closereq = 64
    net.netfilter.nf_conntrack_dccp_timeout_closing = 64
    net.netfilter.nf_conntrack_dccp_timeout_open = 43200
    net.netfilter.nf_conntrack_dccp_timeout_partopen = 480
    net.netfilter.nf_conntrack_dccp_timeout_request = 240
    net.netfilter.nf_conntrack_dccp_timeout_respond = 480
    net.netfilter.nf_conntrack_dccp_timeout_timewait = 240
    net.netfilter.nf_conntrack_events_retry_timeout = 15
    net.netfilter.nf_conntrack_generic_timeout = 600
    net.netfilter.nf_conntrack_icmp_timeout = 30
    net.netfilter.nf_conntrack_sctp_timeout_closed = 10
    net.netfilter.nf_conntrack_sctp_timeout_cookie_echoed = 3
    net.netfilter.nf_conntrack_sctp_timeout_cookie_wait = 3
    net.netfilter.nf_conntrack_sctp_timeout_established = 432000
    net.netfilter.nf_conntrack_sctp_timeout_heartbeat_acked = 210
    net.netfilter.nf_conntrack_sctp_timeout_heartbeat_sent = 30
    net.netfilter.nf_conntrack_sctp_timeout_shutdown_ack_sent = 3
    net.netfilter.nf_conntrack_sctp_timeout_shutdown_recd = 0
    net.netfilter.nf_conntrack_sctp_timeout_shutdown_sent = 0
    net.netfilter.nf_conntrack_tcp_timeout_close = 10
    net.netfilter.nf_conntrack_tcp_timeout_close_wait = 3600
    net.netfilter.nf_conntrack_tcp_timeout_established = 86400
    net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
    net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
    net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
    net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
    net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
    net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
    net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
    net.netfilter.nf_conntrack_udp_timeout = 30
    net.netfilter.nf_conntrack_udp_timeout_stream = 180

    以上均是以秒為單位的超時(shí)值。

對(duì)于通外網(wǎng)的服務(wù)器,考慮調(diào)整以下參數(shù),減少 DDoS 的危害:

  • net.netfilter.nf_conntrack_tcp_timeout_established:默認(rèn) 432000(5 天)

    • 這個(gè)值對(duì)應(yīng)的場(chǎng)景是 “雙方建立了連接后一直不發(fā)包,直到 5 天后才發(fā)”

    • 但默認(rèn) keep-alive 超時(shí)時(shí)間只有 2 小時(shí) 11 分(net.ipv4.tcp_keepalive_time + net.ipv4.tcp_keepalive_intvl * net.ipv4.tcp_keepalive_probes),由于超時(shí)關(guān) socket 不發(fā)包,conntrack 無(wú)法根據(jù)包頭的標(biāo)識(shí)知道狀態(tài)的變化,記錄會(huì)一直處于 ESTABLISHED 狀態(tài),直到 5 天后倒計(jì)時(shí)結(jié)束才刪掉。

    • 空連接攻擊的最佳目標(biāo)。攻擊者把 IP 包頭的源地址改成隨機(jī) IP,握完手就關(guān) socket,用一臺(tái)機(jī)發(fā)請(qǐng)求就能把你的哈希表填滿。

  • net.netfilter.nf_conntrack_tcp_timeout_syn_recv:默認(rèn) 60

    • 類似,故意不發(fā)握手的 ACK 即可。但這個(gè)超時(shí)時(shí)間沒那么夸張,系統(tǒng)也有 syn cookie 機(jī)制來緩解 syn flood 攻擊。

其他值得注意的參數(shù):

  • net.netfilter.nf_conntrack_tcp_timeout_syn_sent:默認(rèn) 120

    • 你的程序的 connect timeout 有這么長(zhǎng)嗎?

  • net.netfilter.nf_conntrack_tcp_timeout_fin_wait:默認(rèn) 120

    • net.ipv4.tcp_fin_timeout 默認(rèn) 60 秒,通常還會(huì)參考 BSD 和 macOS 設(shè)成更小的值。這里往往也沒必要這么大。

  • net.netfilter.nf_conntrack_icmp_timeout:默認(rèn) 30

    • 哪里的 ping 會(huì)等 30 秒才超時(shí)?

這幾個(gè)倒是比較合理,小于等于可能遇到的極端情況,但如果不想半關(guān)閉的連接的記錄繼續(xù)占著寶貴的哈希表,提早清了似乎也沒什么問題:

  • net.netfilter.nf_conntrack_tcp_timeout_time_wait:默認(rèn) 120

    • Linux 里的 MSL 寫死 60 秒(而不是 TCP 標(biāo)準(zhǔn)里拍腦袋的 120 秒),TIME_WAIT 要等 2MSL,這里 120 算是個(gè)合理的值。

    • 但現(xiàn)在默認(rèn)有 PAWS(net.ipv4.tcp_timestamps),不會(huì)出現(xiàn)標(biāo)準(zhǔn)制定時(shí)擔(dān)心的迷途報(bào)文回來碰巧污染了序列號(hào)相同的新連接的數(shù)據(jù)的情況。互聯(lián)網(wǎng)公司基本都開 net.ipv4.tcp_tw_reuse,既然半連接都不留這么久,記錄似乎也不需要留這么久。

  • net.netfilter.nf_conntrack_tcp_timeout_close_wait:默認(rèn) 60

    • CLOSE_WAIT 狀態(tài)是讓被動(dòng)關(guān)閉方把該傳的數(shù)據(jù)傳完。如果程序?qū)懙貌缓?,這里拋了未捕捉的異常,也許就走不到發(fā) FIN 那步了,一直停在這里。

  • net.netfilter.nf_conntrack_tcp_timeout_last_ack:默認(rèn) 30

    • 被動(dòng)關(guān)閉方發(fā) FIN 后如果一直收不到對(duì)面的 ACK 或 RST,會(huì)不斷重發(fā),直到超時(shí)才 CLOSE。net.ipv4.tcp_retries2 的默認(rèn)值是 15,最多要等 924.6 秒……不過一般都會(huì)調(diào)小這個(gè)值。

調(diào)整參數(shù)

添加以下配置參數(shù)到 /etc/sysctl.conf 文件,最后執(zhí)行 sysctl -p

net.netfilter.nf_conntrack_icmp_timeout=10
net.netfilter.nf_conntrack_tcp_timeout_syn_recv=5
net.netfilter.nf_conntrack_tcp_timeout_syn_sent=5
net.netfilter.nf_conntrack_tcp_timeout_established=600
net.netfilter.nf_conntrack_tcp_timeout_fin_wait=10
net.netfilter.nf_conntrack_tcp_timeout_time_wait=10
net.netfilter.nf_conntrack_tcp_timeout_close_wait=10
net.netfilter.nf_conntrack_tcp_timeout_last_ack=10

關(guān)于如何進(jìn)行Linux Netfilter調(diào)優(yōu)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI