1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > java多线程实现端口扫描 使用Java开发多线程端口扫描工具

java多线程实现端口扫描 使用Java开发多线程端口扫描工具

时间:2019-08-25 01:30:19

相关推荐

java多线程实现端口扫描 使用Java开发多线程端口扫描工具

前言:这里只给出命令行版的扫描工具,后续可能是写一个独立的界面,或者是集成到其他工具上去。

一 扫描原理

其实原理非常简单,就是使用Socket去连接目标IP或者域名的指定端口,如果能够连上则说明该端口是打开的。反之,要是在连接超时之前都没有连上,则将该端口判断为关闭状态。下面我将分别说明两种基本的扫描方式:(1)扫描一个连续的端口段;(2)仅扫描一个指定的端口集合

二 使用多线程扫描目标主机一个段的端口开放情况

/**

* 多线程扫描目标主机一个段的端口开放情况

*

* @param ip

* 待扫描IP或域名,eg:180.97.161.184

* @param startPort

* 起始端口

* @param endPort

* 结束端口

* @param threadNumber

* 线程数

* @param timeout

* 连接超时时间

* */

public void scanLargePorts(String ip, int startPort, int endPort,

int threadNumber, int timeout) {

ExecutorService threadPool = Executors.newCachedThreadPool();

for (int i = 0; i < threadNumber; i++) {

ScanMethod1 scanMethod1 = new ScanMethod1(ip, startPort, endPort,

threadNumber, i, timeout);

threadPool.execute(scanMethod1);

}

threadPool.shutdown();

// 每秒中查看一次是否已经扫描结束

while (true) {

if (threadPool.isTerminated()) {

System.out.println("扫描结束");

break;

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36/**

* 多线程扫描目标主机一个段的端口开放情况

*

* @param ip

*待扫描IP或域名,eg:180.97.161.184

* @param startPort

*起始端口

* @param endPort

*结束端口

* @param threadNumber

*线程数

* @param timeout

*连接超时时间

* */

publicvoidscanLargePorts(Stringip,intstartPort,intendPort,

intthreadNumber,inttimeout){

ExecutorServicethreadPool=Executors.newCachedThreadPool();

for(inti=0;i

ScanMethod1scanMethod1=newScanMethod1(ip,startPort,endPort,

threadNumber,i,timeout);

threadPool.execute(scanMethod1);

}

threadPool.shutdown();

// 每秒中查看一次是否已经扫描结束

while(true){

if(threadPool.isTerminated()){

System.out.println("扫描结束");

break;

}

try{

Thread.sleep(1000);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

}

然后是一个内部类ScanMethod1实现了Runnable接口:

/**

* 扫描方式一:针对起始结束端口,进行逐个扫描

*

* */

class ScanMethod1 implements Runnable {

private String ip; // 目标IP

private int startPort, endPort, threadNumber, serial, timeout; // 起始和结束端口,线程数,这是第几个线程,超时时间

/**

* 初始化

*

* @param ip

* 待扫描IP或域名

* @param startPort

* 起始端口

* @param endPort

* 结束端口

* @param threadNumber

* 线程数

* @param serial

* 标记是第几个线程

* @param timeout

* 连接超时时间

* */

public ScanMethod1(String ip, int startPort, int endPort,

int threadNumber, int serial, int timeout) {

this.ip = ip;

this.startPort = startPort;

this.endPort = endPort;

this.threadNumber = threadNumber;

this.serial = serial;

this.timeout = timeout;

}

public void run() {

int port = 0;

try {

InetAddress address = InetAddress.getByName(ip);

Socket socket;

SocketAddress socketAddress;

for (port = startPort + serial; port <= endPort; port += threadNumber) {

socket = new Socket();

socketAddress = new InetSocketAddress(address, port);

try {

socket.connect(socketAddress, timeout); // 超时时间

socket.close();

System.out.println("端口 " + port + " :开放");

} catch (IOException e) {

// System.out.println("端口 " + port + " :关闭");

}

}

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57/**

* 扫描方式一:针对起始结束端口,进行逐个扫描

*

* */

classScanMethod1implementsRunnable{

privateStringip;// 目标IP

privateintstartPort,endPort,threadNumber,serial,timeout;// 起始和结束端口,线程数,这是第几个线程,超时时间

/**

* 初始化

*

* @param ip

*待扫描IP或域名

* @param startPort

*起始端口

* @param endPort

*结束端口

* @param threadNumber

*线程数

* @param serial

*标记是第几个线程

* @param timeout

*连接超时时间

* */

publicScanMethod1(Stringip,intstartPort,intendPort,

intthreadNumber,intserial,inttimeout){

this.ip=ip;

this.startPort=startPort;

this.endPort=endPort;

this.threadNumber=threadNumber;

this.serial=serial;

this.timeout=timeout;

}

publicvoidrun(){

intport=0;

try{

InetAddressaddress=InetAddress.getByName(ip);

Socketsocket;

SocketAddresssocketAddress;

for(port=startPort+serial;port<=endPort;port+=threadNumber){

socket=newSocket();

socketAddress=newInetSocketAddress(address,port);

try{

socket.connect(socketAddress,timeout);// 超时时间

socket.close();

System.out.println("端口 "+port+" :开放");

}catch(IOExceptione){

// System.out.println("端口 " + port + " :关闭");

}

}

}catch(UnknownHostExceptione){

e.printStackTrace();

}

}

}

三 使用多线程扫描目标主机指定Set端口集合的开放情况

/**

* 多线程扫描目标主机指定Set端口集合的开放情况

*

* @param ip

* 待扫描IP或域名,eg:180.97.161.184

* @param portSet

* 待扫描的端口的Set集合

* @param threadNumber

* 线程数

* @param timeout

* 连接超时时间

* */

public void scanLargePorts(String ip, Set portSet,

int threadNumber, int timeout) {

ExecutorService threadPool = Executors.newCachedThreadPool();

for (int i = 0; i < threadNumber; i++) {

ScanMethod2 scanMethod2 = new ScanMethod2(ip, portSet,

threadNumber, i, timeout);

threadPool.execute(scanMethod2);

}

threadPool.shutdown();

while (true) {

if (threadPool.isTerminated()) {

System.out.println("扫描结束");

break;

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33/**

* 多线程扫描目标主机指定Set端口集合的开放情况

*

* @param ip

*待扫描IP或域名,eg:180.97.161.184

* @param portSet

*待扫描的端口的Set集合

* @param threadNumber

*线程数

* @param timeout

*连接超时时间

* */

publicvoidscanLargePorts(Stringip,SetportSet,

intthreadNumber,inttimeout){

ExecutorServicethreadPool=Executors.newCachedThreadPool();

for(inti=0;i

ScanMethod2scanMethod2=newScanMethod2(ip,portSet,

threadNumber,i,timeout);

threadPool.execute(scanMethod2);

}

threadPool.shutdown();

while(true){

if(threadPool.isTerminated()){

System.out.println("扫描结束");

break;

}

try{

Thread.sleep(1000);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

}

具体的线程内部类跟上面类似,代码如下:

/**

* 扫描方式二:针对一个待扫描的端口的Set集合进行扫描

*

* */

private class ScanMethod2 implements Runnable {

private String ip; // 目标IP

private Set portSet; // 待扫描的端口的Set集合

private int threadNumber, serial, timeout; // 线程数,这是第几个线程,超时时间

public ScanMethod2(String ip, Set portSet, int threadNumber,

int serial, int timeout) {

this.ip = ip;

this.portSet = portSet;

this.threadNumber = threadNumber;

this.serial = serial;

this.timeout = timeout;

}

public void run() {

int port = 0;

Integer[] ports = portSet.toArray(new Integer[portSet.size()]); // Set转数组

try {

InetAddress address = InetAddress.getByName(ip);

Socket socket;

SocketAddress socketAddress;

if (ports.length < 1)

return;

for (port = 0 + serial; port <= ports.length - 1; port += threadNumber) {

socket = new Socket();

socketAddress = new InetSocketAddress(address, ports[port]);

try {

socket.connect(socketAddress, timeout);

socket.close();

System.out.println("端口 " + ports[port] + " :开放");

} catch (IOException e) {

// System.out.println("端口 " + ports[port] + " :关闭");

}

}

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45/**

* 扫描方式二:针对一个待扫描的端口的Set集合进行扫描

*

* */

privateclassScanMethod2implementsRunnable{

privateStringip;// 目标IP

privateSetportSet;// 待扫描的端口的Set集合

privateintthreadNumber,serial,timeout;// 线程数,这是第几个线程,超时时间

publicScanMethod2(Stringip,SetportSet,intthreadNumber,

intserial,inttimeout){

this.ip=ip;

this.portSet=portSet;

this.threadNumber=threadNumber;

this.serial=serial;

this.timeout=timeout;

}

publicvoidrun(){

intport=0;

Integer[]ports=portSet.toArray(newInteger[portSet.size()]);// Set转数组

try{

InetAddressaddress=InetAddress.getByName(ip);

Socketsocket;

SocketAddresssocketAddress;

if(ports.length<1)

return;

for(port=0+serial;port<=ports.length-1;port+=threadNumber){

socket=newSocket();

socketAddress=newInetSocketAddress(address,ports[port]);

try{

socket.connect(socketAddress,timeout);

socket.close();

System.out.println("端口 "+ports[port]+" :开放");

}catch(IOExceptione){

// System.out.println("端口 " + ports[port] + " :关闭");

}

}

}catch(UnknownHostExceptione){

e.printStackTrace();

}

}

}

四两种扫描方式的测试用例

public static void main(String[] args) {

PortScanDemo portScanDemo = new PortScanDemo();

//方式1

// portScanDemo.scanLargePorts("ultra-book.co", 20, 10000, 5,800);

// portScanDemo.scanLargePorts("180.97.161.184", 1, 100, 5);

//方式2

Set portSet = new LinkedHashSet();

Integer[] ports = new Integer[] { 21, 22, 23, 25, 26, 69, 80, 110, 143,

443, 465, 995, 1080, 1158, 1433, 1521, 2100, 3128, 3306, 3389,

7001, 8080, 8081, 9080, 9090,43958};

portSet.addAll(Arrays.asList(ports));

portScanDemo.scanLargePorts("ultra-book.co", portSet, 5, 800);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15publicstaticvoidmain(String[]args){

PortScanDemoportScanDemo=newPortScanDemo();

//方式1

// portScanDemo.scanLargePorts("ultra-book.co", 20, 10000, 5,800);

// portScanDemo.scanLargePorts("180.97.161.184", 1, 100, 5);

//方式2

SetportSet=newLinkedHashSet();

Integer[]ports=newInteger[]{21,22,23,25,26,69,80,110,143,

443,465,995,1080,1158,1433,1521,2100,3128,3306,3389,

7001,8080,8081,9080,9090,43958};

portSet.addAll(Arrays.asList(ports));

portScanDemo.scanLargePorts("ultra-book.co",portSet,5,800);

}

五测试结果

注:1 超时时间是以毫秒为单位,其中要是扫描国内的IP可以把这个时间适当设置低一点,200~500左右。相反,要是扫描国外IP就需要把这个时间适当设置大一点,不然有可能把本来打开的端口也漏掉了

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。