2010-06-02 7 views
4

Java의 클라이언트 (특정 IP 당) 당 TCP 요청을 제한하는 방법이 궁금합니다. 예를 들어, 각 클라이언트 IP에 대해 Y 초당 최대 X 개의 요청을 허용하려고합니다. 임시 제한된 IP의 HashSet과 함께 정적 Timer/TimerTask를 사용하는 것을 생각했습니다.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); 

내 문제는 작업을 실행할 때, 소켓 객체가 폐쇄 될 수 있으며, 원격 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의 Map을 타임 스탬프로 유지하여 페이지에 마지막으로 액세스 한 시간을 추적하는 것이 더 쉬울 수도 있습니다. 이렇게하면 클라이언트가 요청을 시작할 때마다이 시간 소인을 간단히 확인할 수 있습니다.

+0

답변 해 주셔서 감사합니다. 나는 아마 당신이 말했듯이지도를 할 것이다. – asmo

+0

이 솔루션의 문제점 : 맵에서 IP를 제거 할시기를 결정하는 방법은 무엇입니까? 왜냐하면 서버가 장시간 실행되면 수천 개의 IP 맵으로 끝나기 때문입니다. – asmo

+0

몇 천명이 문제가되어서는 안되지만 걱정이됩니다. 낡은 IP를 모두 지우려면 지금 (1 시간 이상) 정리를 예약 할 수 있습니다. – Marc

3

하나의 옵션은이를 수행하기 위해 netfilter를 사용하는 것입니다. '순수한'자바가 아니라 가장 강력하고 오류가없는 솔루션 일 것입니다. 차단하기 전에

그냥 즉, (의사), 코드를 빠른 고정 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? hitcount가 int가 아닌가요? – asmo

+0

아, 나는 hitcount를 사용하여지도 과 내가 그것을 얻은 int를 나타냅니다. 혼란 스러울 것입니다. –

+0

이 변경되었습니다. –