我确实在iptables规则中添加了以下规则:
#limit numbeer of connections
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j DROP
iptables -t filter -I INPUT -p tcp --syn --dport 443 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j DROP
iptables -t filter -I INPUT -p tcp --syn --dport 8008 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j DROP
iptables -I INPUT -p tcp --dport 80 -m state --state NEW -m recent
--set iptables -I INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 2 --hitcount 25 -j DROP iptables -I INPUT -p tcp --dport 443 -m state --state NEW -m recent --set iptables -I INPUT
-p tcp --dport 443 -m state --state NEW -m recent --update --seconds 2 --hitcount 25 -j DROP iptables -I INPUT -p tcp --dport 8008 -m state --state NEW -m recent --set iptables -I INPUT -p tcp --dport 8008 -m state --state NEW -m recent --update --seconds 2 --hitcount 25 -j DROP
这是完整的iptables规则的样子:
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 3 TTL-Match name: sshprobe side: source mask: 255.255.255.255
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh state NEW recent: SET name: sshprobe side: source mask: 255.255.255.255
DROP tcp -- anywhere anywhere tcp dpt:8008 state NEW recent: UPDATE seconds: 2 hit_count: 25 name: DEFAULT side: source mask: 255.255.255.255
tcp -- anywhere anywhere tcp dpt:8008 state NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255
DROP tcp -- anywhere anywhere tcp dpt:https state NEW recent: UPDATE seconds: 2 hit_count: 25 name: DEFAULT side: source mask: 255.255.255.255
tcp -- anywhere anywhere tcp dpt:https state NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255
DROP tcp -- anywhere anywhere tcp dpt:http state NEW recent: UPDATE seconds: 2 hit_count: 25 name: DEFAULT side: source mask: 255.255.255.255
tcp -- anywhere anywhere tcp dpt:http state NEW recent: SET name: DEFAULT side: source mask: 255.255.255.255
DROP tcp -- anywhere anywhere tcp dpt:8008 flags:FIN,SYN,RST,ACK/SYN #conn src/32 > 15
DROP tcp -- anywhere anywhere tcp dpt:https flags:FIN,SYN,RST,ACK/SYN #conn src/32 > 15
DROP tcp -- anywhere anywhere tcp dpt:http flags:FIN,SYN,RST,ACK/SYN #conn src/32 > 15
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:http-alt
ACCEPT tcp -- anywhere anywhere tcp dpt:8181
ACCEPT tcp -- anywhere anywhere tcp dpt:https
ACCEPT tcp -- anywhere anywhere tcp dpt:8008
DROP all -- anywhere anywhere
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
我想测试这项新政策是否有效。
我如何测试它?我尝试使用apache基准来检查来自我的localhost的某些连接是否正在丢弃:
ab -n 10000 -c 9000 http://www.tralev.com/web/main
但是从输出中我看不到任何连接掉了:
Failed requests: 82
(Connect: 0, Receive: 0, Length: 82, Exceptions: 0)
(此长度错误可能是由于服务器上的某些动态内容造成的)。
那么我如何修复我的iptables设置或设置一个测试,显示当前设置实际上限制了从IP地址到15(以及每秒最大连接数为15)的连接数?
答案 0 :(得分:0)
由于没有人回复此消息超过24小时,我编写了一个Java代码来测试服务器响应。代码如下,供参考。顺便说一句,似乎我的iptables规则不起作用(执行代码)。
public class TestConcurrentCalls {
class Tester implements Runnable {
String url;
boolean error;
TestConcurrentCalls parent;
public Tester(String url, TestConcurrentCalls parent) {
this.url = url;
this.parent = parent;
}
@Override
public void run() {
String content = WebOperations.getFromURL(url).toString();
if (content == null || content.length() < 10) {
synchronized (parent) {
parent.errors++;
}
} else {
synchronized (parent) {
parent.ok++;
}
}
}
}
static public int errors = 0;
static public int ok = 0;
public void test(String url, int threads) {
for (int thread = 0; thread < threads; thread++) {
testOne(url);
}
int sleeps = 0;
try {
do {
Thread.sleep(1000L);
sleeps++;
} while (threads > errors + ok || sleeps > 1000);
} catch (InterruptedException ex) {
Logger.getLogger(TestConcurrentCalls.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void testOne(String url) {
Tester tester = new Tester(url, this);
Thread thread = new Thread(tester);
thread.start();
}
public static void main(String[] args) {
TestConcurrentCalls test = new TestConcurrentCalls();
test.test("http://www.tralev.com/web/main", 1000);
System.out.println("Errors: " + errors + " , ok: " + ok);
}
}
此代码使用我的内部WebOperations.getFromUrl方法,该方法编写如下:
public static StringBuilder getFromURL(String address) {
return getFromURL(address, null);
}
public static StringBuilder getFromURL(String address,String referer) {
return getFromURL(address, referer, 60, null); // wait one minute at most
}
public static StringBuilder getFromURL(String address,String referer, int maxSecondsToWait, String accept) {
StringBuilder result=new StringBuilder();
try {
if(!address.toLowerCase().contains("://"))
address="http://"+address;
Logger.getLogger(WebOperations.class.getName()).info("URL for fetching " + address);
URL url = new URL(address);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(maxSecondsToWait * 1000);
if (accept != null) {
connection.setRequestProperty("Accept", accept);
}
connection.setReadTimeout(maxSecondsToWait * 1000);
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)");
//connection.setRequestProperty("Accept","*/*");
if (referer != null && !referer.equals("")) {
connection.setRequestProperty("From", referer);
connection.setRequestProperty("Referer", referer);
}
// Get all cookies from the server.
// Note: The first call to getHeaderFieldKey() will implicit send
// the HTTP request to the server.
for (int i = 0;; i++) {
String headerName = connection.getHeaderFieldKey(i);
String headerValue = connection.getHeaderField(i);
if (headerName == null && headerValue == null) {
// No more headers
break;
}
if ("Set-Cookie".equalsIgnoreCase(headerName)) {
// Parse cookie
String[] fields = headerValue.split(";\\s*");
String cookieValue = fields[0];
String expires = null;
String path = null;
String domain = null;
boolean secure = false;
// Parse each field
for (int j = 1; j < fields.length; j++) {
if ("secure".equalsIgnoreCase(fields[j])) {
secure = true;
} else if (fields[j].indexOf('=') > 0) {
String[] f = fields[j].split("=");
if ("expires".equalsIgnoreCase(f[0])) {
expires = f[1];
} else if ("domain".equalsIgnoreCase(f[0])) {
domain = f[1];
} else if ("path".equalsIgnoreCase(f[0])) {
path = f[1];
}
}
}
// Save the cookie...
}
}
int responseCode = 200;
//try {
//responseCode = connection.getResponseCode();
//} catch (SocketException e) {
// Logger.getLogger(WebOperations.class.getName()).log(Level.SEVERE, e.getMessage(), e);
//}
if (responseCode >= 400 && responseCode < 600) {
return result;
}
String contentType = connection.getContentType();
if (contentType == null) {
contentType = "html";
}
String nameContentType=contentType.toLowerCase();
if(nameContentType.contains("html") || nameContentType.contains("text") || nameContentType.contains("txt") || nameContentType.contains("json") || nameContentType.contains("json")) {
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null ) {
result.append(inputLine).append("\n");
}
in.close();
}
} catch (Exception e) {
if(e instanceof MalformedURLException) {
System.err.println("MalformedURLException for "+address);
}
//System.err.println(e.getMessage());
Logger.getLogger(WebOperations.class.getName()).log(Level.WARNING, "Exception while reading web page", e);
}
return result;
}