2010-06-02 69 views
4

我在想如何限制Java中每個客戶端(每個特定IP)的TCP請求。例如,我希望允許每個客戶端IP每Y個請求最多X個請求。我想到使用靜態Timer/TimerTask與臨時受限IP的HashSet結合使用。限制每個IP的TCP請求

private static final Set<InetAddress> restrictedIPs = Collections.synchronizedSet(new HashSet<InetAddress>()); 

private static final Timer restrictTimer = new Timer(); 

因此,當用戶連接到服務器時,我自己的IP地址添加到限制列表中,並啓動任務取消限制他X秒。

restrictedIPs.add(socket.getInetAddress()); 

restrictTimer.schedule(new TimerTask() 
{ 
    public void run() 
    { 
    restrictedIPs.remove(socket.getInetAddress()); 
    } 

}, MIN_REQUEST_INTERVAL); 

我的問題是,在當時的任務將運行,Socket對象可以被關閉,遠程IP地址將無法訪問了...

任何想法歡迎!另外,如果有人知道一個Java框架內置的方式來實現這一點,我真的很想聽到它。

回答

1

這種簡單的解決辦法是:

final InetAddress ip = socket.getInetAddress(); 
restrictedIPs.add(ip); 

restrictTimer.schedule(new TimerTask() 
{ 
    public void run() 
    { 
    restrictedIPs.remove(ip); 
    } 

}, MIN_REQUEST_INTERVAL); 

這種方法的問題在於,它需要額外的線程刪除限制IP地址。也許將InetAddress地圖保留爲時間戳更容易,以跟蹤他們上次訪問頁面的時間。這樣,每次客戶端啓動請求時,您都可以簡單地檢查此時間戳。

+0

感謝您的回答!正如你所說,我可能會做一個地圖。 – asmo 2010-06-02 08:24:47

+0

就這個解決方案的問題:如何確定何時從地圖上刪除IP?因爲如果服務器運行很長時間,它最終將會包含數千個IP地圖。 – asmo 2010-06-02 08:50:56

+0

幾千不應該是一個問題,但我理解你的關心。您可以安排每隔一小時左右執行一次清理,以刪除所有舊的IP(比一個小時更早)。 – Marc 2010-06-02 08:53:55

3

一種選擇是使用netfilter來完成此操作。不是'純粹'的java,但可能是最健壯和沒有錯誤的解決方案。

如果只想快速解決您的代碼,保存的IP地址,並添加一個數,您塊之前,即(僞):

IPaddress addr = socket.getAddress(); 
int hitcount = hitcountMap.get(addr).value(); 
if (hitcount <= HIT_MAX) { 
    //only increase if person hasn't reached roof, prevents 'overblocking' 
    hitcountMap.get(addr).increase(); 
    unblockTimer.schedule(hitcountMap.get(addr).decrease(), BLOCK_TIMEOUT); 
} 
if (hitcount > HIT_MAX) { 
    connection.drop(); 
} 

debian-administration

iptables -I INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent \ 
    --set 

iptables -I INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent \ 
    --update --seconds 60 --hitcount 4 -j DROP 

編輯拍攝這個例子這應該使BLOCK_TIMEOUT達到最大值(不保證沒有錯誤)。您應該考慮使用信號量進行計數,因爲您可能(可能)會從多個線程運行此代碼,具體取決於您的線程模型。

+0

hitcount.get?是不是一個int? – asmo 2010-06-02 08:22:49

+0

哦,我用hitcount來表示地圖和我從它得到的int。混亂,會改變。 – 2010-06-02 08:26:35

+0

那裏改變了。 – 2010-06-02 08:27:52