1. 程式人生 > >ftp關鍵技術五:限制連結數

ftp關鍵技術五:限制連結數

通常在一些網站中,為了防止惡意大量的訪問和超大量訪問導致記憶體佔滿,會對單個連結的連線數和總連結數做出一個限制。

​ 以本FTP服務端為例,假設每個客戶連結,我們都需要兩個程序來處理它,假設了一個客戶需要分配總共1M的棧記憶體出來,1000個連結,接近1G的記憶體就沒有了。另一方面,如果單個ip大量連結服務端,會佔用大量的頻寬、記憶體和檔案控制代碼,實際上每個使用者(ip)只需要兩三個連結就可以解決問題,所以對單個ip連線數進行限制,有助於維持服務端的效能穩定和防止惡意訪問。

​ 在系統自帶vsftpd中有如下的配置檔案

max_clients=300 最大客戶端連線數為300
max_per_ip=10 每個IP最大連線數

​ 現在我們知道,我們需要一個數據結構來儲存ip和ip對應的連結數,所以我們首先想到的就是用鍵值對模型,即每個ip對應一個連結數,並存儲起來,並且我們需要能夠快速插入、刪除和查詢,適合的就是樹和hash表。但是連線數真的能解決問題嗎?

​ <!-- more -->

​ 首先,何時連結,我們何時增加一個連線數這個毋容置疑,但是,我們要如何知道這個連結結束了呢?我們可以在程序結束的時候,獲得程序結束的訊號,從而感知到一個程序的結束,所以這個時候,我們就不能單單依靠連線數,而是依靠程序的pid來對應ip。

​ 所以我們需要兩個hash表,一個hash表是pid to ip,另一個表是ip to conn。

​ 至於hash_table我們可以自己定製寫一個,也可以用stl庫中的,但是還是自己寫一個吧,我們只需要用到hash_table的部分功能。

​ 下面的函式只是對主要的成員函式進行註釋,方便理解(這裡並沒用泛型,而是借鑑了redis的實現方式用void *實現的hashtable)。

void* hash_lookup_entry(void* key, unsigned int key_size);
//尋找並返回key所對應的value, 如value為空,則返回空。
void hash_add_entry(void *key, unsigned int key_size,
                        void *value, unsigned int value_size);
//新增一個key-value
void hash_free_entry(void *key, unsigned int key_size);
//刪除一個key-value

​ 下面我們需要兩個表

static hash* s_ip_conn_hash;
static hash* s_pid_ip_hash;

​ 在接受連結成功後,我們可以獲得一個unsigned int型別的ip,我們可以根據這個ip,找到ip所對應的p_count,再對p_count進行操作就完成了ip-conn的建立和增長。

        unsigned int ip = addr.sin_addr.s_addr;
        sess.num_this_ip = handle_ip_count(&ip);
                ......
        unsigned int handle_ip_count(void *ip)
        {
            unsigned int count;
            unsigned int *p_count = (unsigned int*)s_ip_conn_hash->hash_lookup_entry(ip, sizeof(unsigned int));
            if (p_count == NULL)
            {
                count = 1;
                //不存在即建立
                s_ip_conn_hash->hash_add_entry(ip, sizeof(unsigned int), &count, sizeof(unsigned int));
            }
            else
            {
                //存在便增1,不過沒有考慮到原子操作,失誤失誤
                count = *p_count;
                ++count;
                *p_count = count;
            }
            return count;
        }

為了減少主程序的工作,我們將檢測連結過限制放到子程序中。

        if (pid == 0)    //子程序
        {
               ...
            check_limits(&sess);
               ...
        }
        void check_limits(session_t *sess)
        {
            if (tunable_max_clients > 0 && sess->num_clients > tunable_max_clients)
            {
                ftp_reply(sess, FTP_TOO_MANY_USERS, "There are too many connection, please try later");
                exit(EXIT_FAILURE);
            }
            if (tunable_max_per_ip > 0 && sess->num_this_ip > tunable_max_per_ip)
            {
                ftp_reply(sess, FTP_IP_LIMIT, "There are too many connection,from internet address");
                exit(EXIT_FAILURE);
            }
        }

​ 在連結數的刪除上,我們需要明白一個流程。

​ 1.建立/增加 ip-value

​ 2.在父程序中建立pid-ip鍵值對

​ 3.在父程序中檢測到子程序的退出

​ 4.查詢pid對應的ip,刪除ip對於的兩個鍵值對。

​ 那如何實現檢測呢?我們可以設定一個訊號,當檢測到SIGCHLD時候,執行操作四。

        signal(SIGCHLD, handle_sighid);
                //接受連結後
        if (pid == 0)    //子程序
        {
            //防止子程序的子程序退出的干擾
            signal(SIGCHLD, SIG_IGN);
        }
        //檢測到子程序退出後執行
        void handle_sighid(int sig)
        {
            pid_t pid;
            while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
            {
                --s_children;
                unsigned int*ip = (unsigned int *)s_pid_ip_hash->hash_lookup_entry(&pid, sizeof(pid));  //查詢pid對於的ip
                if (ip == NULL)
                {
                    continue;
                }
                drop_ip_count(ip);    //對ip-value減一或者刪除操作
                s_pid_ip_hash->hash_free_entry(&pid, sizeof(pid));
            }
        }
​
        void drop_ip_count(void *ip)
        {
            unsigned int count;
            unsigned int *p_count = (unsigned  int *)s_ip_conn_hash->hash_lookup_entry(ip, sizeof(unsigned int));
            if (p_count == NULL)
            {
               return;
            }
​
            count = *p_count;
            if (count <= 0)
            {
                s_ip_conn_hash->hash_free_entry(ip, sizeof(unsigned int));
                return;
            }
            --count;
            *p_count = count;
            if (count == 0)
            {
                s_ip_conn_hash->hash_free_entry(ip, sizeof(unsigned int));
            }
        }
​

歡迎大家討論和分享問題。

相關推薦

ftp關鍵技術:限制連結

通常在一些網站中,為了防止惡意大量的訪問和超大量訪問導致記憶體佔滿,會對單個連結的連線數和總連結數做出一個限制。 ​ 以本FTP服務端為例,假設每個客戶連結,我們都需要兩個程序來處理它,假設了一個客戶需要分配總共1M的棧記憶體出來,1000個連結,接近1G的記憶體就沒有了。

論文:基於據挖掘的網絡入侵檢測關鍵技術研究-郭春

行數 base 進行 href 向量 設計 分類算法 lse 檢測方法 目錄 1、文章主要工作: 1.1 設計了一種適用於入侵檢測的特征提取方法。(降維)DSFE:Distance-sum based feature extraction method; 1.2 設計了一

限制連線上漲的幾個關鍵因素

系統埠限制 Linux系統埠為short型別表示,數值上限為65535。假設分配壓測業務可用埠範圍為1024 - 65535(1024以下系統預留),不考慮可能還執行著其它對外連線的服務,真正可用埠也就是64000左右(實際上,一般為了方便計算,一般直接設定為50000)。換言之,即在一臺機器上一個IP,可

FTP限制連線

FTP連線數限制問題 問題描述:因業務增長,所需要的FTP併發量增加,導致客戶端連線FTP server時出現報錯 Troubleshooting: 1>報錯內容:單個IP連線過多。 2>限制客戶端連線數的引數: max_clients  #最大客戶

Devops關鍵工具及技術()—基於Pipeline的Bash指令碼部署

接下來我們將會為Pipeline加上部署的Stage,部署採用sh指令碼進行部署。後續我們將會採用Ansible的自動化部署。 Sh指令碼 沿用之前的Spring-boot工程,經過持續整合後,我們將會得到maven構建後的一個jar包,這個jar即是工程的啟

章——演示版保護技術-時間限制,選單功能限制

時間限制程式一種為每次執行時長10.20分鐘後停止,必須重新啟動。計時器有如下選擇: 1.setTime()函式 此函式可以在程式呼叫的時候,指定一個時間,同時獲取一個超時後的回撥函式。如果超過這個時間,系統則會給計時器視窗傳送WM_TIMER,或者呼叫程式提供的回撥函式 函式原型

檢視/修改linux系統的最大連結限制/檔案描述符限制/埠範圍限制/虛擬記憶體等

一、修改最大連線數 1、檢視當前檔案描述符的限制數目的命令: ulimit -n 2、修改檔案描述符的限制數目 2.1 臨時改變當前會話: ulimit -n 65536 2.2 永久變更需要下面兩個步驟: 1) 修改/etc/security/limits.c

篇:據預處理(二) - 異常值處理

ges 方向 分享 site 方式 得到 ros 聚類 測試 前言 數據中如果有某個值偏離該列其他值比較離譜,那麽就有可能是一個異常的值。在數據預處理中,自然需要把這個異常值檢測出來,然後剔除掉,或者光滑掉,或者其他各種方法進行處理。 需要註

物聯網關鍵技術

不為 internet rfi intern zigbee 網絡 技術 nfc 網關 不出戶而知天下。不窺牘而見天道。其出彌遠,其知彌少。是以聖人不行而知,不見而名,不為而成。 Internet of Thing IoT 1.物聯網技術概述 2.無線傳感器網絡 3.ZigB

九度 題目1394:連擊

ace 一個 using return include pop turn span printf 轉載請註明本文鏈接http://blog.csdn.net/yangnanhai93/article/details/40506571 題目鏈接:http://ac.job

Python入門系列教程()函

st3 python入門 test print 缺省 .com 教程 技術 log 全局變量 修改全局變量 a=100 def test(): global a a=200 print a 多個返回值 缺省參數 d

oracle sql 基礎():據定義語言(創建和管理序列、索引、同義詞)

aps span 最小值 into 全表掃描 條件 creat 返回 ext 許多應用程序要求使用唯一的數字作為主鍵的值,你即可以在應用程序中構建代碼來處理這種需求,也可以用一個序列來產生唯一的數字。如果你想要增進某些查詢的性能,你應該考慮創建一個索引,你也可

視頻轉碼成mp4格式,添加關鍵幀,添加元據,把元據放在第一幀

回車 perf res player 執行 href 如果 www 路徑 作者測試是在windows下使用,所以下載的頁面地址是: http://ffmpeg.zeranoe.com/builds/點擊頁面上的Download FFmpeg git-738ebb4 64-b

C語言基礎-第課-函

多少 main函數 聲明 width 編程 sig borde cnblogs 一個人 1 函數 1.1 函數的原型和調用 在使用函數前必須定義或者聲明函數 double circle(double r); int main() { double l

Hadoop Ls命令添加顯示條限制

實現 處理 objects none ada indicate isp 基本 tex 前言在hadoop的FsShell命令中,預計非常多人比較經常使用的就是hadoop fs -ls,-lsr,-cat等等這種與Linux系統中差點兒一致的文件系統相關的命令.可是細致

SpringMVC詳解()------參綁定

@override 占用 通過 問題 顯示 led prop -s 意義   參數綁定,簡單來說就是客戶端發送請求,而請求中包含一些數據,那麽這些數據怎麽到達 Controller ?這在實際項目開發中也是用到的最多的,那麽 SpringMVC 的參數綁定是怎麽實現的呢?下

ES6之主要知識點()函

call() line [] 簡寫 過大 get color 復雜 obj 函數參數的默認值 作用域 var x = 1; function f(x, y = x) { console.log(y); } f(2) // 2 let x = 1; funct

《Linux命令行與shell腳本編程大全》第十章 呈現

orm while 永久 date txt 沒有 電子 必須 document 15.1 理解輸入和輸出 現在知道兩種顯示腳本輸出的方法 1)在顯示器屏幕上顯示 2)將輸出文件重定向到文件中 15.1.1 標準文件描述符 Linux系統將每個對象當做文件處理。這包括輸入和數

對比感知技術的硬件或者算法的關鍵技術指標

gpo 幀率 功耗 範圍 tex 復雜 交叉 iphone 感知 關鍵技術規格: 1.檢測範圍; 2.檢測精度; 3.檢測角度; 4.幀率。 5.模塊大小 6.功耗 目前了解到的有:雙目視覺, 單點TOF, 3D TOF,3D結構光, 單攝像頭深度(成像時的P

【JavaScript的種基本據類型及轉換】

空字符串 ali 就是 false col eight 字符串 變量的數據類型 輸出 js中有六種數據類型,包括五種基本數據類型(Number,String,Boolean,Null,Undefined),和一種混合數據類型就是特殊的(Object)。 "undefi