如何用JAVA实现TCP connect、TCP SYN和TCP FIN端口扫描
connect比较简单,就是用Socket+多线程,每个端口创建一次连接,没连上是不会往下执行的,会抛出异常,网上有源码,都是这个方法。
syn和FIN还不知道咋实现,可以考虑用本地方法。
多线程(端口扫描器)是如何提高程序的执行效率的?
可以不要多线程。如果是阻塞式就必须要多线程。
多线程当然是并发运行的(当然还要考虑同步问题),多线程可以最大化利用CPU资源,可以大大提高程序效率。
Python 实现端口扫描
一、常见端口扫描的原理
0、秘密扫描
秘密扫描是一种不被审计工具所检测的扫描技术。
它通常用于在通过普通的防火墙或路由器的筛选(filtering)时隐藏自己。
秘密扫描能躲避IDS、防火墙、包过滤器和日志审计,从而获取目标端口的开放或关闭的信息。由于没有包含TCP 3次握手协议的任何部分,所以无法被记录下来,比半连接扫描更为隐蔽。
但是这种扫描的缺点是扫描结果的不可靠性会增加,而且扫描主机也需要自己构造IP包。现有的秘密扫描有TCP FIN扫描、TCP ACK扫描、NULL扫描、XMAS扫描和SYN/ACK扫描等。
1、Connect()扫描
此扫描试图与每一个TCP端口进行“三次握手”通信。如果能够成功建立接连,则证明端口开发,否则为关闭。准确度很高,但是最容易被防火墙和IDS检测到,并且在目标主机的日志中会记录大量的连接请求以及错误信息。
TCP connect端口扫描服务端与客户端建立连接成功(目标端口开放)的过程:
① Client端发送SYN;
② Server端返回SYN/ACK,表明端口开放;
③ Client端返回ACK,表明连接已建立;
④ Client端主动断开连接。
建立连接成功(目标端口开放)
TCP connect端口扫描服务端与客户端未建立连接成功(目标端口关闭)过程:
① Client端发送SYN;
② Server端返回RST/ACK,表明端口未开放。
优点:实现简单,对操作者的权限没有严格要求(有些类型的端口扫描需要操作者具有root权限),系统中的任何用户都有权力使用这个调用,而且如果想要得到从目标端口返回banners信息,也只能采用这一方法。
另一优点是扫描速度快。如果对每个目标端口以线性的方式,使用单独的connect()调用,可以通过同时打开多个套接字,从而加速扫描。
缺点:是会在目标主机的日志记录中留下痕迹,易被发现,并且数据包会被过滤掉。目标主机的logs文件会显示一连串的连接和连接出错的服务信息,并且能很快地使它关闭。
2、SYN扫描
扫描器向目标主机的一个端口发送请求连接的SYN包,扫描器在收到SYN/ACK后,不是发送的ACK应答而是发送RST包请求断开连接。这样,三次握手就没有完成,无法建立正常的TCP连接,因此,这次扫描就不会被记录到系统日志中。这种扫描技术一般不会在目标主机上留下扫描痕迹。但是,这种扫描需要有root权限。
·端口开放:(1)Client发送SYN;(2)Server端发送SYN/ACK;(3)Client发送RST断开(只需要前两步就可以判断端口开放)
·端口关闭:(1)Client发送SYN;(2)Server端回复RST(表示端口关闭)
优点:SYN扫描要比TCP Connect()扫描隐蔽一些,SYN仅仅需要发送初始的SYN数据包给目标主机,如果端口开放,则相应SYN-ACK数据包;如果关闭,则响应RST数据包;
3、NULL扫描
反向扫描—-原理是将一个没有设置任何标志位的数据包发送给TCP端口,在正常的通信中至少要设置一个标志位,根据FRC 793的要求,在端口关闭的情况下,若收到一个没有设置标志位的数据字段,那么主机应该舍弃这个分段,并发送一个RST数据包,否则不会响应发起扫描的客户端计算机。也就是说,如果TCP端口处于关闭则响应一个RST数据包,若处于开放则无相应。但是应该知道理由NULL扫描要求所有的主机都符合RFC 793规定,但是windows系统主机不遵从RFC 793标准,且只要收到没有设置任何标志位的数据包时,不管端口是处于开放还是关闭都响应一个RST数据包。但是基于Unix(*nix,如Linux)遵从RFC 793标准,所以可以用NULL扫描。 经过上面的分析,我们知道NULL可以辨别某台主机运行的操作系统是什么操作系统。
端口开放:Client发送Null,server没有响应
端口关闭:(1)Client发送NUll;(2)Server回复RST
说明:Null扫描和前面的TCP Connect()和SYN的判断条件正好相反。在前两种扫描中,有响应数据包的表示端口开放,但在NUll扫描中,收到响应数据包表示端口关闭。反向扫描比前两种隐蔽性高些,当精确度也相对低一些。
用途:判断是否为Windows系统还是Linux。
4、FIN扫描
与NULL有点类似,只是FIN为指示TCP会话结束,在FIN扫描中一个设置了FIN位的数据包被发送后,若响应RST数据包,则表示端口关闭,没有响应则表示开放。此类扫描同样不能准确判断windows系统上端口开发情况。
·端口开放:发送FIN,没有响应
·端口关闭:(1)发送FIN;(2)回复RST
5、ACK扫描
扫描主机向目标主机发送ACK数据包。根据返回的RST数据包有两种方法可以得到端口的信息。方法一是: 若返回的RST数据包的TTL值小于或等于64,则端口开放,反之端口关闭。
6、Xmas-Tree扫描
通过发送带有下列标志位的tcp数据包。
·URG:指示数据时紧急数据,应立即处理。
·PSH:强制将数据压入缓冲区。
·FIN:在结束TCP会话时使用。
正常情况下,三个标志位不能被同时设置,但在此种扫描中可以用来判断哪些端口关闭还是开放,与上面的反向扫描情况相同,依然不能判断windows平台上的端口。
·端口开放:发送URG/PSH/FIN,没有响应
·端口关闭:(1)发送URG/PSH/FIN,没有响应;(2)响应RST
XMAS扫描原理和NULL扫描的类似,将TCP数据包中的ACK、FIN、RST、SYN、URG、PSH标志位置1后发送给目标主机。在目标端口开放的情况下,目标主机将不返回任何信息。
7、Dump扫描
也被称为Idle扫描或反向扫描,在扫描主机时应用了第三方僵尸计算机扫描。由僵尸主机向目标主机发送SYN包。目标主机端口开发时回应SYN|ACK,关闭时返回RST,僵尸主机对SYN|ACK回应RST,对RST不做回应。从僵尸主机上进行扫描时,进行的是一个从本地计算机到僵尸主机的、连续的ping操作。查看僵尸主机返回的Echo响应的ID字段,能确定目标主机上哪些端口是开放的还是关闭的。
二、Python 代码实现
1、利用Python的Socket包中的connect方法,直接对目标IP和端口进行连接并且尝试返回结果,而无需自己构建SYN包。
2、对IP端口进行多线程扫描,注意的是不同的电脑不同的CPU每次最多创建的线程是不一样的,如果创建过多可能会报错,需要根据自己电脑情况修改每次扫描的个数或者将seelp的时间加长都可以。
看完了吗?感觉动手操作一下把!
python学习网,免费的在线学习python平台,欢迎关注!
本文转自:
Asynchronous socket error 10061
服务器错误,
端口扫描的问题
在写端口扫描时 ,如果与某主机特定端口无法通信 ,
就此主机而言 ,我想应该有以下两种情况 :
1 。此地址上无任何主机存在
2 。有主机但被扫描的特定端口不存在 ( 也可能是被 firewall 过滤了 )
如何得知某端口一打开
给你来个简单的吧!
procedure TForm1.Timer1Timer(Sender: TObject);
var
I : integer;
begin
Memo1.Clear;
for I := 0 to 1000 do begin
ServerSocket1.Close;
ServerSocket1.Port := I;
try
ServerSocket1.Open;
except
Memo1.Lines.Add(IntToStr(I) + ' 端口被打开 !');
end;
end;
end;
对不起 ,我指的是别人机器上的 PORT
你是说 PORT 只能被一个程序打开么 ?
可是 ,我用 OICQ 时在打开 4000 没问题呀
我把上面的程序改了一下 ,也可以用的。你就去试图连接对方 ,如果通了 ,说明此端口被打
开。
procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add(' 端口 '+IntToStr(Socket.RemotePort)+' 被打开! ');
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
ClientSocket1.Close;
ClientSocket1.Port := PortID;
try
ClientSocket1.Open;
except
end;
Inc(PortID);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
PortID := 1;
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
try
ClientSocket1.Close;
except
end;
Memo2.Lines.add(IntToStr(Socket.remotePort));
end;
吕雪松你的方法我试过了可是抱错 :asynchronous socket error 10061
--------------------------------------------------------------------------------
来自 :xueminliu 时间 :01-3-3 17:26:47 ID:464312
要区分 tcp 和 udp
oicq 用 udp 协议 ,connect 没有用 ,但是 tcp 可以这样
另外 ,如果你写扫描程序可千万不要这样 ,应该使用别的链接方法 ,否则你的踪迹会被别人
发现 .例如使用 sys 扫描或者 fin 扫描 :
我给你异步 socket 的 api 代码 :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,WInSock, ExtCtrls;
const WM_SOCKET=WM_USER+1; //socket 消息
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Panel1: TPanel;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
Sockhd : integer; //socket 句柄
Serv_Addr : Tsockaddr;// 目标地址
procedure SockEvent(var msg: Tmessage);message WM_SOCKET; // 处理 cocket 消息
procedure DspMsg(msg : string); // 显示信息
{ Private declarations }
public
{ Public declarations }
end;
Form1: TForm1;
implementation
{$R *.DFM}
function lookup_hostname(const hostname:string):longint; // 把域名转化成 IP 地址
var
RemoteHost : PHostEnt; (* no, don't free it! *)
ip_address: longint;
begin
ip_address:=-1;
try
if hostname='' then
begin (* no host given! *)
lookup_hostname:=ip_address;
EXIT;
end
else
begin
ip_address:=Winsock.Inet_Addr(PChar(hostname)); (* try a xxx.xxx.xxx.xx first *)
if ip_address=SOCKET_ERROR then begin
RemoteHost:=Winsock.GetHostByName(PChar(hostname));
if (RemoteHost=NIL) or (RemoteHost^.h_length=0) then
begin
lookup_hostname:=ip_address;
EXIT; (* host not found *)
end
else
ip_address:=longint(pointer(RemoteHost^.h_addr_list^)^);
end;
end;
except
ip_address:=-1;
end;
lookup_hostname:=ip_address;
end;
procedure TFOrm1.DspMsg(msg: string);
begin
memo1.Lines.Add(msg+'...');
if Memo1.Lines.Count200 then Memo1.Lines.Delete(0);
end;
procedure TForm1.SockEvent(var msg : tmessage); // 处理 socket 消息
begin
case msg.LParam of
FD_READ: begin // 标识可以读数据 ,当然肯定已经链接上了
dspmsg(' 可以读取数据 ');
//do what you want do
end;
FD_WRITE: begin
dspmsg(' 可以发送数据 ');
//do what you want do
end;
FD_ERROR: begin
dspmsg(' 发生错误 ');
// 如果你是客户端 ,则应该是连接不上 ,即端口没有开
end;
FD_CLOSE: Begin
dspmsg(' 服务器断开连接 ');
// 对方关闭连接
end;
FD_CONNECT: begin
dspmsg(' 连结上服务器 ');
// 表示对方端口开放
end;
FD_ACCEPT: begin
dspmsg(' 接收一个请求 ');
// 这个消息只有服务端可能出现
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var wsaData:TwsaData;
begin // 启动 winsock 动态链接库
if WSAStartup (makeword(2,2), wsaData)0 then begin
messagebox(application.handle,' 无法启动 winsock 动态连接库 !',' 警告 ',MB_OK or MB_APPLMODAL or MB_ICONWARNING);
Application.Terminate;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin // 关闭 dll
WSACleanup;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Sockhd := socket(AF_INET,SOCK_STREAM,0); // 创建 socket 句柄
if Sockhd0 then begin
messagebox(application.handle,' 无法创建句柄 !',' 警告 ',MB_OK or MB_APPLMODAL or MB_ICONWARNING);
exit;
end;
Serv_addr.sin_addr.s_addr:= lookup_hostname(edit1.Text); // 主机名
Serv_addr.sin_family := PF_INET;
Serv_addr.sin_port := htons(23); //any port you want to connect
if WSAAsyncSelect(Sockhd,Form1.handle,WM_SOCKET,FD_ACCEPT or FD_CONNECT or FD_CLOSE or FD_READ or FD_WRITE)=SOCKET_ERROR
then begin
messagebox(application.handle,' 无法创建句柄 !',' 警告 ',MB_OK or MB_APPLMODAL or MB_ICONWARNING);
exit;
end; // 异步 socket
connect(sockhd,serv_addr,sizeof(serv_addr)); // 连接 ,结果会在前面的处理函数处理
end;
end.
相信应该可以满足你的要求
请问如何编程区分这两种情况
最好详细一点喔 ( 我很笨的 )
如果在此地址上无主机存在 ,则发出的数据包得不到回应 ,应用程序会等待超时才
认为连接失败 ( 被 firewall 过滤时情况一样 ),若有主机但被扫描的特定端口不存在时 ,
该主机会发出目的端口不存在的应答
至于如何编程实现 ,应该可以由错误码来判断 ,在 OnError 事情中判定 ErrorCode 是多
小 ,再分别处理 ,ErrorCode 的详情参见 Help
这么高深的问题才 50 分 ,少了
端口扫描不是这么简单 ,否则大家都做
首先你扫描人家的端口会留下自己的痕迹 ,系统有日志可以察看
因此我们做端口扫描的的时候绝对不会直接连接别人 ,而是通过地层的接口编程
例如在 TCP 三次握手的第三次放弃 ,对方就不会有日志 ,这称为 sys 扫描
给对方端口发断开连接的请求称为 fin 扫描 .
通过这两种扫描方式都可以得知对方的端口是否开 ,而且不会留下痕迹 .
总之端口扫描里面有很多学问 ,不是这里可以说清除的
怎么做呀 ,如你所说的话好象要直接调用 socket api?
我现在首先关心的是我提出的问题 ,如何编程区分这两种情况 :
1 。此地址上无任何主机存在
2 。有主机但被扫描的特定端口不存在 ( 也可能是被 firewall 过滤了 )
还有 ,为什么我把 clientsocket 的 onread 里的 errorcode 设为 0 了 ,
还是常常会出现 delphi 自己的错误消息提示 ,象 10061,10057 什么的 ,
这好象是另外一种 error code,如能把它屏蔽我想就不会出现提示了 .
是吗?如果是 ,该怎么做呢。
最后 : 如果能给我一个多线程的端口扫描源码 ,我再给 100 分 ( 真的很穷啊 )
我找到了 help 里的有关说明 ( 是在索引中 Error TCP Event 里找到的 )
WinSock Error Codes
The following error codes apply to the WinSock ActiveX Controls.
Error Code Error Message
10004 The operation is canceled.
10013 The requested address is a broadcast address, but flag is not set.
10014 Invalid argument.
10022 Socket not bound, invalid address or listen is not invoked prior to accept.
10024 No more file descriptors are available, accept queue is empty.
10035 Socket is non-blocking and the specified operation will block.
10036 A blocking Winsock operation is in progress.
10037 The operation is completed. No blocking operation is in progress.
10038 The descriptor is not a socket.
10039 Destination address is required.
10040 The datagram is too large to fit into the buffer and is truncated.
10041 The specified port is the wrong type for this socket.
10042 Option unknown, or unsupported.
10043 The specified port is not supported.
10044 Socket type not supported in this address family.
10045 Socket is not a type that supports connection oriented service.
10047 Address Family is not supported.
10048 Address in use.
10049 Address is not available from the local machine.
10050 Network subsystem failed.
10051 The network cannot be reached from this host at this time.
10052 Connection has timed out when SO_KEEPALIVE is set.
10053 Connection is aborted due to timeout or other failure.
10054 The connection is reset by remote side.
10055 No buffer space is available.
10056 Socket is already connected.
10057 Socket is not connected.
10058 Socket has been shut down.
10060 The attempt to connect timed out.
10061 Connection is forcefully rejected.
10201 Socket already created for this object.
10202 Socket has not been created for this object.
11001 Authoritative answer: Host not found.
11002 Non-Authoritative answer: Host not found.
11003 Non-recoverable errors.
11004 Valid name, no data record of requested type.
我想只要对它进行有关操作就能完全屏蔽 winsocket 错误消息 ( 至少
能屏蔽很多 onerror 里的 errorcode 参数无法屏蔽的消息 )
我终于找到原因所在了
在打开 Socket 时也要捕获异常
try
ClientSocket.Open;
except
MessageBox(MainForm.Handle,'Error connecting to this address','Connect',MB_ICONEXCLAMATION);
end;
在 OnError 中最后要将 ErrorCode 置为 0
if ErrorEvent=eeConnect then
begin
Socket.Close;
MessageBox(MainForm.Handle,'Error connecting to this address','Connect',MB_ICONEXCLAMATION);
end
else if ErrorEvent=eeSend then
Socket.Close;
ErrorCode:=0;
你可能无做第一步
而这样也可以区分你所说的两种情况
1 。第二步 OnError 就是此地址上无任何主机存在 ,到超时就触发 OnError 事件
2 。第一步捕捉到异常就是有主机但被扫描的特定端口不存在
java扫描局域网的端口
直接上代码:
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class PortScanner extends Thread {
private int[] p;
Socket ss = null;
public PortScanner(int[] p) {
this.p = p;
}
public static void main(String[] args) {
for (int i = 0; i 65535; i = i + 100) {
new PortScanner(new int[] { i + 1, i + 100 }).start();
}
}
@Override
public void run() {
for (int i = p[0]; i p[1]; i++) {
try {
ss = new Socket("8.8.8.8", i);
System.out.println("扫描到端口: " + i);
} catch (Exception e) {
// System.out.println("关闭端口: " + i);
}
}
}
}
0条大神的评论