Windows下實現屏蔽IP的功能,很多人可能會聯想到使用一些復雜的技術來解決,比如NDIS中間層驅動,甚至NDIS鈎子驅動。但這些技術太過深奧,只有精通Windows編程的人才玩得轉。如果你對Windows編程不是特別了解又沒有太多時間,或者你根本一竅不通,那么你可以試試采用Windows網絡配置命令netsh來解決這些問題。
本文是采用IPSec策略來實現此功能。Windows 2000/XP/2003平台最早就提供了這個工具,考慮到兼容性的問題Windows之后的版本同樣也提供了,只是在此基礎上還增加了新的功能advfirewall(本文不予探討,有興趣的可以點擊鏈接查看)。
IPSec策略的配置有兩種方法,前提是IPSec服務已經啟動:
- 運行secpol.msc,進入IP安全策略再進一步定制安全策略,這里不詳述。
- 進入命令行下執行netsh ipsec命令,配置IPSec策略。PS:netsh ipsec命令不是很復雜,盡管官方文檔特別長,看起來有點嚇人。
先介紹一下IPSec策略的基本組成:
一個IPSec策略通常由一個或者多個規則組成;每個規則由一個IP篩選器列表和一個對應的篩選器操作組成;這個篩選器列表和篩選器可以是系統本身所沒有的,如果沒有則需要自行建立,而一個篩選器又由一個或多個篩選器組成。
因此配置IPSec的時候必須要分步進行。規則由篩選器列表和篩選器操作構成,而且存放在策略里,策略器由策略器列表來存儲。這樣就決定了一個步驟:
建立空的安全策略 -> 建立篩選器列表 -> 建立篩選器操作 -> 指派策略
看一下下面的例子就明白了,這是我從別人博客上拿過來的例子:
'建立一個名字叫XBLUE的安全策略先 netsh ipsec static add policy name=XBLUE '建立一個ip篩選器,指定192.168.1.2 netsh ipsec static add filterlist name=denyip netsh ipsec static add filter filterlist=denyip srcaddr=192.168.1.2 dstaddr=Me dstport=3389 protocol=TCP '建立一個篩選器操作 netsh ipsec static add filteraction name=denyact action=block '加入規則到安全策略XBLUE netsh ipsec static add rule name=kill3389 policy=XBLUE filterlist=denyip filteraction=denyact '激活這個策略 netsh ipsec static set policy name=XBLUE assign=y '把安全策略導出 netsh ipsec static exportpolicy d:\ip.ipsec '刪除所有安全策略 netsh ipsec static del all '把安全策略導入 netsh ipsec static importpolicy d:\ip.ipsec '激活這個策略 netsh ipsec static set policy name=策略名稱 assign=y
大家可以根據這個例子在命令行里面嘗試,同時你也可以在命令行下查看命令參數的說明,很方便。
有了前面的這些做鋪墊,后面的程序就好寫了。我要實現的功能很簡單,可以指定單個IP地址、單個IP地址和端口號或存有IP地址信息的文件(每行可以是單個IP地址或者單個IP地址和端口號)為輸入。如果地址沒有給定端口號,將該地址屏蔽;如果地址給定了端口號,屏蔽該地址對應端口的TCP和UDP協議。
在實現程序前,編寫了兩個批處理腳本用來支撐本程序的運行:備份本地安全策略.bat和還原本地安全策略.bat。簡而言之就是在程序運行前先備份,必要時還原即可。

1 @echo off 2 cls 3 netsh ipsec static exportpolicy ip.ipsec 4 netsh ipsec static delete all 5 netsh ipsec static add policy name=abandon 6 netsh ipsec static add filterlist name=denyip 7 netsh ipsec static add filter filterlist=denyip srcaddr=192.168.1.2 dstaddr=me dstport=3389 protocol=UDP 8 netsh ipsec static add filteraction name=denyact action=block 9 netsh ipsec static add rule name=killu policy=abandon filterlist=denyip filteraction=denyact 10 netsh ipsec static set policy name=abandon assign=y 11 pause 12 exit

1 @echo off 2 cls 3 4 netsh ipsec static delete all 5 netsh ipsec static importpolicy ip.ipsec 6 netsh ipsec static set policy name=local assign=y 7 pause 8 exit
貼上程序代碼,很簡單理解,不多說。
1 package cn.edu; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.util.regex.Matcher; 8 import java.util.regex.Pattern; 9 import java.lang.InterruptedException; 10 11 /** 12 * 13 * @author kelvin 14 * 15 * 指定一個IP列表文件或IP地址,並將文件中所有對應的IP地址和端口號或指定的IP地址和端口號過濾 16 * 指令格式: IPFilter type [filename|IPAddr] 17 * type類型:-f表示文件 18 * -a表示IP地址 19 * IP地址格式: [IP]:[port] 或 [IP] 20 * eg: java IPFilter -f ip.txt 21 * java IPFilter -a 192.168.1.1:80 22 * java IPFilter -a 192.168.1.1 23 */ 24 public class IPFilter { 25 26 // [IP]:[port]正則表達式 27 private static final String IPADDRESS_PORT_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 28 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 29 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 30 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5]):([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$"; 31 32 // IP地址正則表達式 33 private static final String IPADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 34 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 35 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." 36 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"; 37 38 // 篩選器列表名稱 39 private static final String FILTER_LIST_NAME = "denyip"; 40 41 /** 42 * @param args 43 * @throws IOException, InterruptedException 44 */ 45 public static void main(String[] args) throws IOException, InterruptedException { 46 if (args.length != 2) { 47 printUsage(); 48 return; 49 } 50 51 Pattern ip_port_pattern = Pattern.compile(IPADDRESS_PORT_PATTERN); 52 Pattern ip_pattern = Pattern.compile(IPADDRESS_PATTERN); 53 if (args[0].equals("-f")) { 54 File filterFile = null; 55 BufferedReader br = null; 56 String ipAddr = null; 57 try { 58 filterFile = new File(args[1]); 59 if(!filterFile.exists()) { 60 System.out.println(args[1]+"不存在"); 61 return; 62 } 63 64 br = new BufferedReader(new FileReader(filterFile)); 65 66 while ((ipAddr = br.readLine()) != null) { 67 if (ipAddr.length() <= 0) 68 continue; 69 70 if (ip_port_pattern.matcher(ipAddr).matches()) { // [IP]:[port] 71 72 String ipAddrDetail[] = ipAddr.split(":"); 73 74 // 可保留前兩個或后兩個,也可以全寫 75 // me -> [IP]:[port] TCP 76 Runtime.getRuntime().exec( 77 "netsh ipsec static add filter filterlist=" 78 + FILTER_LIST_NAME 79 + " srcaddr=me dstaddr=" 80 + ipAddrDetail[0] 81 + " dstport=" 82 + ipAddrDetail[1] 83 +" protocol=TCP").waitFor(); 84 85 // me -> [IP]:[port] UDP 86 Runtime.getRuntime().exec( 87 "netsh ipsec static add filter filterlist=" 88 + FILTER_LIST_NAME 89 + " srcaddr=me dstaddr=" 90 + ipAddrDetail[0] 91 + " dstport=" 92 + ipAddrDetail[1] 93 +" protocol=UDP").waitFor(); 94 95 // [IP]:[port] -> me TCP 96 Runtime.getRuntime().exec( 97 "netsh ipsec static add filter filterlist=" 98 + FILTER_LIST_NAME 99 + " srcaddr=" 100 + ipAddrDetail[0] 101 +" dstaddr=me srcport=" 102 + ipAddrDetail[1] 103 + " protocol=TCP").waitFor(); 104 105 // [IP]:[port] -> me UDP 106 Runtime.getRuntime().exec( 107 "netsh ipsec static add filter filterlist=" 108 + FILTER_LIST_NAME 109 + " srcaddr=" 110 + ipAddrDetail[0] 111 +" dstaddr=me srcport=" 112 + ipAddrDetail[1] 113 + " protocol=TCP").waitFor(); 114 115 System.out.println("已過濾" + ipAddr); 116 } else if(ip_pattern.matcher(ipAddr).matches()) { 117 // 保留其中一個即可,也可以全寫 118 // me -> [IP] 119 Runtime.getRuntime().exec( 120 "netsh ipsec static add filter filterlist=" 121 + FILTER_LIST_NAME 122 + " srcaddr=me dstaddr=" 123 + ipAddr 124 + " protocol=ANY").waitFor(); 125 126 // [IP] -> me 127 Runtime.getRuntime().exec( 128 "netsh ipsec static add filter filterlist=" 129 + FILTER_LIST_NAME 130 + " srcaddr=" 131 + ipAddr 132 +" dstaddr=me protocol=ANY").waitFor(); 133 System.out.println("已過濾" + ipAddr); 134 } else { 135 System.out.println(ipAddr + "不是合法的格式"); 136 } 137 } 138 } catch (Exception e) { 139 e.printStackTrace(); 140 } finally { 141 if (br != null) { 142 br.close(); 143 br = null; 144 } 145 } 146 System.out.println("done!"); 147 } else if (args[0].equals("-a")) { 148 if (ip_pattern.matcher(args[1]).matches()) { 149 // me -> [IP] 150 Runtime.getRuntime().exec( 151 "netsh ipsec static add filter filterlist=" 152 + FILTER_LIST_NAME + " srcaddr=me dstaddr=" 153 + args[1] 154 + " protocol=ANY").waitFor(); 155 156 // [IP] -> me 157 Runtime.getRuntime().exec( 158 "netsh ipsec static add filter filterlist=" 159 + FILTER_LIST_NAME + " srcaddr=" 160 + args[1] 161 +" dstaddr=me protocol=ANY").waitFor(); 162 163 System.out.println("已過濾" + args[1]); 164 } else if(ip_port_pattern.matcher(args[1]).matches()) { 165 String ipAddrDetail[] = args[1].split(":"); 166 167 // me -> [IP]:[port] TCP 168 Runtime.getRuntime().exec( 169 "netsh ipsec static add filter filterlist=" 170 + FILTER_LIST_NAME 171 + " srcaddr=me dstaddr=" 172 + ipAddrDetail[0] 173 + " dstport=" 174 + ipAddrDetail[1] 175 + " protocol=TCP").waitFor(); 176 177 // me -> [IP]:[port] UDP 178 Runtime.getRuntime().exec( 179 "netsh ipsec static add filter filterlist=" 180 + FILTER_LIST_NAME 181 + " srcaddr=me dstaddr=" 182 + ipAddrDetail[0] 183 + " dstport=" 184 + ipAddrDetail[1] 185 + " protocol=UDP").waitFor(); 186 187 // [IP]:[port] -> me UDP 188 Runtime.getRuntime().exec( 189 "netsh ipsec static add filter filterlist=" 190 + FILTER_LIST_NAME 191 + " srcaddr=" 192 + ipAddrDetail[0] 193 +" dstaddr=me" 194 + " srcport=" 195 + ipAddrDetail[1] 196 + " protocol=UDP").waitFor(); 197 198 // [IP]:[port] -> me TCP 199 Runtime.getRuntime().exec( 200 "netsh ipsec static add filter filterlist=" 201 + FILTER_LIST_NAME 202 + " srcaddr=" 203 + ipAddrDetail[0] 204 +" dstaddr=me" 205 + " srcport=" 206 + ipAddrDetail[1] 207 + " protocol=TCP").waitFor(); 208 209 System.out.println("已過濾" + args[1]); 210 } else { 211 System.out.println(args[1] + "不是合法的格式"); 212 } 213 } else { 214 printUsage(); 215 } 216 217 } 218 219 static void printUsage() { 220 System.out.println("Usage:IPFilter type [filename|IPAddr]"); 221 System.out.println("type: [-f | -a]"); 222 System.out.println(" -f filename"); 223 System.out.println(" -a IPAddr"); 224 } 225 226 }
編譯完成后,可以執行查看運行結果:
1. 屏蔽117.30.180.209:19122,執行以下命令:
java cn.edu.IPFilter -a 117.30.180.209:19122
2. 屏蔽屏蔽117.30.180.209,執行以下命令:
java cn.edu.IPFilter -a 117.30.180.209
3. 屏蔽ip.txt中地址信息,執行以下命令:
java cn.edu.IPFilter -f ip.txt

1 118.166.7.250:11638 2 75.40.16.53 3 117.30.189.209:19122