怎么添加網(wǎng)站百度網(wǎng)盤下載電腦版官方下載
承接前面幾篇文章的觀點,本文用一個安全攻擊的例子說明為了解決一個傷害很低的低概率問題,會引入多么大的麻煩,這次是可怕的被攻擊 (⊙o⊙)。
TCP 端口號只有 16bit,序列號只有 32bit,這意味著在強大攻擊算力面前,它很容易會被 Blind In-Window Attacks 傷害。比如,如果一個針對知名服務(wù)器 80 端口的攻擊者恰好猜對了 sport,并且使用 in_window 的序列號偽造了 SYN 報文(or RST,Data…)發(fā)給服務(wù)端,服務(wù)器將重置正常的連接,這種攻擊隨著主機內(nèi)存的增加從而 window 的增加而更加容易。
為了讓這種 Blind In-Window Attacks 更難以實施,RFC5961 引入了 Challenge ACK 的概念,如果收到莫名其妙的異常報文(比如異常 SYN,RST),將重置的責(zé)任推給發(fā)送方:
- 向發(fā)送方發(fā)一個 Challenge ACK,如果果真是發(fā)送方發(fā)生了異常,收到 Challenge ACK 后自然會自行 RST 連接,否則就是遭受了 Blind In-Window Attack。
多么好的創(chuàng)意,卻弄巧成拙。
設(shè)計者意識到 Blind In-Window Attacks 可能會帶來海量的 Challenge ACK 報文注入網(wǎng)絡(luò)占用帶寬資源,從而導(dǎo)致另一類 DDoS Attack,于是提出 ACK Throttling 方案:在固定時間段(比如 1 分鐘)只發(fā)送固定數(shù)量(比如 100)個 Challenge ACK。
是不是很完美?是也不是,說 “是” 因為想到的問題都解決了,說 “不是” 因為總有想不到的。下面是一個閉環(huán):
- 為解決 Blind In-Win Attacks => 引入 Challenge ACK => 造成潛在 DDoS => 引入 ACK Throttling => 為 Blind In-Win Attack 提供了有效信息 => Blind In-Win Attack 實施更容易,不再 Blind!
下面是一個攻擊圖示:
如 Linux 常規(guī)配置的 Throttling thresh 是 1 分鐘 100 次,攻擊者只需要與熟知端口服務(wù)器創(chuàng)建正常連接,然后發(fā)送一個猜測的 sport,seq 攜帶 SYN 的報文,緊接著在 1 分鐘內(nèi)在合法連接 conn-2 中發(fā)送 100 個 In-Win 的 RST,如果攻擊者收到了 100 個 Challenge ACK,說明猜錯了,繼續(xù)改變 sport,seq,如果它收到了 99 個 Challenge ACK,說明猜對了,因為有一個 Challenge ACK 發(fā)給了被攻擊者 A,是不是很有趣?
緊接著,知道了 sport,攻擊者便可以用同樣的方法猜測 seq 和 ack 來注入數(shù)據(jù)了。是不是機關(guān)算計太聰明,反誤了卿卿性命?
針對這(又一個,yet another)個問題,我曾經(jīng)本想著提交一個派池,不再用固定的 threshold,而是用隨機數(shù),一會兒換一個,當(dāng)我查代碼時,發(fā)現(xiàn)在 4.7 版本已經(jīng)更正了:
/* RFC 5961 7 [ACK Throttling] */
static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
{.../* Then check host-wide RFC 5961 rate limit. */now = jiffies / HZ;if (now != challenge_timestamp) {u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1;challenge_timestamp = now;WRITE_ONCE(challenge_count, half +prandom_u32_max(sysctl_tcp_challenge_ack_limit));}count = READ_ONCE(challenge_count);if (count > 0) {WRITE_ONCE(challenge_count, count - 1);NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);tcp_send_ack(sk);}
}
而在此之前,它長這樣:
/* RFC 5961 7 [ACK Throttling] */
static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
{.../* Then check the check host-wide RFC 5961 rate limit. */now = jiffies / HZ;if (now != challenge_timestamp) {challenge_timestamp = now;challenge_count = 0;}if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);tcp_send_ack(sk);}
}
但天知道會不會有引入另一個問題,一定會。
講這個故事的技術(shù)細節(jié)不是本意,我想表達的是,不要為解決一件小事而引入復(fù)雜的機制。回到 RFC5961 之前,SYN,RST 的 Blind In-Win Attack 發(fā)生多嗎?成功概率大嗎?不是因為它有可能發(fā)生就一定要去解決它。此外,針對安全問題,我一向的觀點是 “不與陌生人說話”,你說的每句話都在透露信息,如果非要說,那么 “說謊,并且每次說不同的謊”,真相不重要,重要的是指紋,不要讓人猜到你的特征。
浙江溫州皮鞋濕,下雨進水不會胖。