请给出TCP connect()这个函数的所有参数及其解释?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请给出TCP connect()这个函数的所有参数及其解释?相关的知识,希望对你有一定的参考价值。

所有参数及其解释如下:

-sT

TCP connect()扫描:这是最基本的TCP扫描方式。connect()是一种系统调用,由操作系统提供,用来打开一个连接。如果目标端口有程序监听,connect()就会成功返回,否则这个端口是不可达的。这项技术最大的优点是,你勿需root权限。任何UNIX用户都可以自由使用这个系统调用。这种扫描很容易被检测到,在目标主机的日志中会记录大批的连接请求以及错误信息。

-sS

TCP同步扫描(TCP SYN):因为不必全部打开一个TCP连接,所以这项技术通常称为半开扫描(half-open)。你可以发出一个TCP同步包(SYN),然后等待回应。如果对方返回SYN|ACK(响应)包就表示目标端口正在监听;如果返回RST数据包,就表示目标端口没有监听程序;如果收到一个SYN|ACK包,源主机就会马上发出一个RST(复位)数据包断开和目标主机的连接,这实际上有我们的操作系统内核自动完成的。这项技术最大的好处是,很少有系统能够把这记入系统日志。不过,你需要root权限来定制SYN数据包。

-sF -sF -sN

秘密FIN数据包扫描、圣诞树(Xmas Tree)、空(Null)扫描模式:即使SYN扫描都无法确定的情况下使用。一些防火墙和包过滤软件能够对发送到被限制端口的SYN数据包进行监视,而且有些程序比如synlogger和courtney能够检测那些扫描。这些高级的扫描方式可以逃过这些干扰。这些扫描方式的理论依据是:关闭的端口需要对你的探测包回应RST包,而打开的端口必需忽略有问题的包(参考RFC 793第64页)。FIN扫描使用暴露的FIN数据包来探测,而圣诞树扫描打开数据包的FIN、URG和PUSH标志。不幸的是,微软决定完全忽略这个标准,另起炉灶。所以这种扫描方式对Windows95/NT无效。不过,从另外的角度讲,可以使用这种方式来分别两种不同的平台。如果使用这种扫描方式可以发现打开的端口,你就可以确定目标注意运行的不是Windows系统。如果使用-sF、-sX或者-sN扫描显示所有的端口都是关闭的,而使用SYN扫描显示有打开的端口,你可以确定目标主机可能运行的是Windwos系统。现在这种方式没有什么太大的用处,因为nmap有内嵌的操作系统检测功能。还有其它几个系统使用和windows同样的处理方式,包括Cisco、BSDI、HP/UX、MYS、IRIX。在应该抛弃数据包时,以上这些系统都会从打开的端口发出复位数据包。

-sP

ping扫描:有时你只是想知道此时网络上哪些主机正在运行。通过向你指定的网络内的每个IP地址发送ICMP echo请求数据包,nmap就可以完成这项任务。如果主机正在运行就会作出响应。不幸的是,一些站点例如:microsoft.com阻塞ICMP echo请求数据包。然而,在默认的情况下nmap也能够向80端口发送TCP ack包,如果你收到一个RST包,就表示主机正在运行。nmap使用的第三种技术是:发送一个SYN包,然后等待一个RST或者SYN/ACK包。对于非root用户,nmap使用connect()方法。

在默认的情况下(root用户),nmap并行使用ICMP和ACK技术。

注意,nmap在任何情况下都会进行ping扫描,只有目标主机处于运行状态,才会进行后续的扫描。如果你只是想知道目标主机是否运行,而不想进行其它扫描,才会用到这个选项。

-sU

UDP扫描:如果你想知道在某台主机上提供哪些UDP(用户数据报协议,RFC768)服务,可以使用这种扫描方法。nmap首先向目标主机的每个端口发出一个0字节的UDP包,如果我们收到端口不可达的ICMP消息,端口就是关闭的,否则我们就假设它是打开的。

有些人可能会想UDP扫描是没有什么意思的。但是,我经常会想到最近出现的solaris rpcbind缺陷。rpcbind隐藏在一个未公开的UDP端口上,这个端口号大于32770。所以即使端口111(portmap的众所周知端口号)被防火墙阻塞有关系。但是你能发现大于30000的哪个端口上有程序正在监听吗?使用UDP扫描就能!cDc Back Orifice的后门程序就隐藏在Windows主机的一个可配置的UDP端口中。不考虑一些通常的安全缺陷,一些服务例如:snmp、tftp、NFS使用UDP协议。不幸的是,UDP扫描有时非常缓慢,因为大多数主机限制ICMP错误信息的比例(在RFC1812中的建议)。例如,在Linux内核中(在net/ipv4/icmp.h文件中)限制每4秒钟只能出现80条目标不可达的ICMP消息,如果超过这个比例,就会给1/4秒钟的处罚。solaris的限制更加严格,每秒钟只允许出现大约2条ICMP不可达消息,这样,使扫描更加缓慢。nmap会检测这个限制的比例,减缓发送速度,而不是发送大量的将被目标主机丢弃的无用数据包。

不过Micro$oft忽略了RFC1812的这个建议,不对这个比例做任何的限制。所以我们可以能够快速扫描运行Win95/NT的主机上的所有65K个端口。

-sA

ACK扫描:这项高级的扫描方法通常用来穿过防火墙的规则集。通常情况下,这有助于确定一个防火墙是功能比较完善的或者是一个简单的包过滤程序,只是阻塞进入的SYN包。

这种扫描是向特定的端口发送ACK包(使用随机的应答/序列号)。如果返回一个RST包,这个端口就标记为unfiltered状态。如果什么都没有返回,或者返回一个不可达ICMP消息,这个端口就归入filtered类。注意,nmap通常不输出unfiltered的端口,所以在输出中通常不显示所有被探测的端口。显然,这种扫描方式不能找出处于打开状态的端口。

-sW

对滑动窗口的扫描:这项高级扫描技术非常类似于ACK扫描,除了它有时可以检测到处于打开状态的端口,因为滑动窗口的大小是不规则的,有些操作系统可以报告其大小。这些系统至少包括:某些版本的AIX、Amiga、BeOS、BSDI、Cray、Tru64 UNIX、DG/UX、OpenVMS、Digital UNIX、OpenBSD、OpenStep、QNX、Rhapsody、SunOS 4.x、Ultrix、VAX、VXWORKS。从nmap-hackers邮件3列表的文档中可以得到完整的列表。

-sR

RPC扫描。这种方法和nmap的其它不同的端口扫描方法结合使用。选择所有处于打开状态的端口向它们发出SunRPC程序的NULL命令,以确定它们是否是RPC端口,如果是,就确定是哪种软件及其版本号。因此你能够获得防火墙的一些信息。诱饵扫描现在还不能和RPC扫描结合使用。

-b

FTP反弹攻击(bounce attack):FTP协议(RFC 959)有一个很有意思的特征,它支持代理FTP连接。也就是说,我能够从evil.com连接到FTP服务器target.com,并且可以要求这台FTP服务器为自己发送Internet上任何地方的文件!1985年,RFC959完成时,这个特征就能很好地工作了。然而,在今天的Internet中,我们不能让人们劫持FTP服务器,让它向Internet上的任意节点发送数据。如同Hobbit在1995年写的文章中所说的,这个协议"能够用来做投递虚拟的不可达邮件和新闻,进入各种站点的服务器,填满硬盘,跳过防火墙,以及其它的骚扰活动,而且很难进行追踪"。我们可以使用这个特征,在一台代理FTP服务器扫描TCP端口。因此,你需要连接到防火墙后面的一台FTP服务器,接着进行端口扫描。如果在这台FTP服务器中有可读写的目录,你还可以向目标端口任意发送数据(不过nmap不能为你做这些)。

传递给-b功能选项的参数是你要作为代理的FTP服务器。语法格式为:

-b username:password@server:port。

除了server以外,其余都是可选的。如果你想知道什么服务器有这种缺陷,可以参考我在Phrack 51发表的文章。还可以在nmap的站点得到这篇文章的最新版本。

4.2 通用选项

这些内容不是必需的,但是很有用。

-P0

在扫描之前,不必ping主机。有些网络的防火墙不允许ICMP echo请求穿过,使用这个选项可以对这些网络进行扫描。microsoft.com就是一个例子,因此在扫描这个站点时,你应该一直使用-P0或者-PT 80选项。

-PT

扫描之前,使用TCP ping确定哪些主机正在运行。nmap不是通过发送ICMP echo请求包然后等待响应来实现这种功能,而是向目标网络(或者单一主机)发出TCP ACK包然后等待回应。如果主机正在运行就会返回RST包。只有在目标网络/主机阻塞了ping包,而仍旧允许你对其进行扫描时,这个选项才有效。对于非root用户,我们使用connect()系统调用来实现这项功能。使用-PT 来设定目标端口。默认的端口号是80,因为这个端口通常不会被过滤。

-PS

对于root用户,这个选项让nmap使用SYN包而不是ACK包来对目标主机进行扫描。如果主机正在运行就返回一个RST包(或者一个SYN/ACK包)。

-PI

设置这个选项,让nmap使用真正的ping(ICMP echo请求)来扫描目标主机是否正在运行。使用这个选项让nmap发现正在运行的主机的同时,nmap也会对你的直接子网广播地址进行观察。直接子网广播地址一些外部可达的IP地址,把外部的包转换为一个内向的IP广播包,向一个计算机子网发送。这些IP广播包应该删除,因为会造成拒绝服务攻击(例如smurf)。

-PB

这是默认的ping扫描选项。它使用ACK(-PT)和ICMP(-PI)两种扫描类型并行扫描。如果防火墙能够过滤其中一种包,使用这种方法,你就能够穿过防火墙。

-O

这个选项激活对TCP/IP指纹特征(fingerprinting)的扫描,获得远程主机的标志。换句话说,nmap使用一些技术检测目标主机操作系统网络协议栈的特征。nmap使用这些信息建立远程主机的指纹特征,把它和已知的操作系统指纹特征数据库做比较,就可以知道目标主机操作系统的类型。

-I

这个选项打开nmap的反向标志扫描功能。Dave Goldsmith 1996年向bugtap发出的邮件注意到这个协议,ident协议(rfc 1413)允许使用TCP连接给出任何进程拥有者的用户名,即使这个进程并没有初始化连接。例如,你可以连接到HTTP端口,接着使用identd确定这个服务器是否由root用户运行。这种扫描只能在同目标端口建立完全的TCP连接时(例如:-sT扫描选项)才能成功。使用-I选项是,远程主机的identd精灵进程就会查询在每个打开的端口上监听的进程的拥有者。显然,如果远程主机没有运行identd程序,这种扫描方法无效。

-f

这个选项使nmap使用碎片IP数据包发送SYN、FIN、XMAS、NULL。使用碎片数据包增加包过滤、入侵检测系统的难度,使其无法知道你的企图。不过,要慎重使用这个选项!有些程序在处理这些碎片包时会有麻烦,我最喜欢的嗅探器在接受到碎片包的头36个字节时,就会发生segmentation faulted。因此,在nmap中使用了24个字节的碎片数据包。虽然包过滤器和防火墙不能防这种方法,但是有很多网络出于性能上的考虑,禁止数据包的分片。

注意这个选项不能在所有的平台上使用。它在Linux、FreeBSD、OpenBSD以及其它一些UNIX系统能够很好工作。

-v

冗余模式。强烈推荐使用这个选项,它会给出扫描过程中的详细信息。使用这个选项,你可以得到事半功倍的效果。使用-d选项可以得到更加详细的信息。

-h

快速参考选项。

-oN

把扫描结果重定向到一个可读的文件logfilename中。

-oM

把扫描结果重定向到logfilename文件中,这个文件使用主机可以解析的语法。你可以使用-oM -来代替logfilename,这样输出就被重定向到标准输出stdout。在这种情况下,正常的输出将被覆盖,错误信息荏苒可以输出到标准错误stderr。要注意,如果同时使用了-v选项,在屏幕上会打印出其它的信息。

-oS thIs l0gz th3 r3suLtS of YouR ScanZ iN a s| THe fiL3 U sPecfy 4s an arGuMEnT! U kAn gIv3 the 4rgument -

(wItHOUt qUOteZ) to sh00t output iNT0 stDouT!@!! 莫名其妙,下面是我猜着翻译的,相形字?

把扫描结果重定向到一个文件logfilename中,这个文件使用一种"黑客方言"的语法形式(作者开的玩笑?)。同样,使用-oS -就会把结果重定向到标准输出上。

-resume

某个网络扫描可能由于control-C或者网络损失等原因被中断,使用这个选项可以使扫描接着以前的扫描进行。logfilename是被取消扫描的日志文件,它必须是可读形式或者机器可以解析的形式。而且接着进行的扫描不能增加新的选项,只能使用与被中断的扫描相同的选项。nmap会接着日志文件中的最后一次成功扫描进行新的扫描。

-iL

从inputfilename文件中读取扫描的目标。在这个文件中要有一个主机或者网络的列表,由空格键、制表键或者回车键作为分割符。如果使用-iL -,nmap就会从标准输入stdin读取主机名字。你可以从指定目标一节得到更加详细的信息。

-iR

让nmap自己随机挑选主机进行扫描。

-p

这个选项让你选择要进行扫描的端口号的范围。例如,-p 23表示:只扫描目标主机的23号端口。-p 20-30,139,60000-表示:扫描20到30号端口,139号端口以及所有大于60000的端口。在默认情况下,nmap扫描从1到1024号以及nmap-services文件(如果使用RPM软件包,一般在/usr/share/nmap/目录中)中定义的端口列表。

-F

快速扫描模式,只扫描在nmap-services文件中列出的端口。显然比扫描所有65535个端口要快。

-D

使用诱饵扫描方法对目标网络/主机进行扫描。如果nmap使用这种方法对目标网络进行扫描,那么从目标主机/网络的角度来看,扫描就象从其它主机(decoy1,等)发出的。从而,即使目标主机的IDS(入侵检测系统)对端口扫描发出报警,它们也不可能知道哪个是真正发起扫描的地址,哪个是无辜的。这种扫描方法可以有效地对付例如路由跟踪、response-dropping等积极的防御机制,能够很好地隐藏你的IP地址。

每个诱饵主机名使用逗号分割开,你也可以使用ME选项,它代表你自己的主机,和诱饵主机名混杂在一起。如果你把ME放在第六或者更靠后的位置,一些端口扫描检测软件几乎根本不会显示你的IP地址。如果你不使用ME选项,nmap会把你的IP地址随机夹杂在诱饵主机之中。

注意:你用来作为诱饵的主机应该正在运行或者你只是偶尔向目标发送SYN数据包。很显然,如果在网络上只有一台主机运行,目标将很轻松就会确定是哪台主机进行的扫描。或许,你还要直接使用诱饵的IP地址而不是其域名,这样诱饵网络的域名服务器的日志上就不会留下关于你的记录。

还要注意:一些愚蠢的端口扫描检测软件会拒绝路由试图进行端口扫描的主机。因而,你需要让目标主机和一些诱饵断开连接。如果诱饵是目标主机的网关或者就是其自己时,会给目标主机造成很大问题。所以你需要慎重使用这个选项。

诱饵扫描既可以在起始的ping扫描也可以在真正的扫描状态下使用。它也可以和-O选项组合使用。

使用太多的诱饵扫描能够减缓你的扫描速度甚至可能造成扫描结果不正确。同时,有些ISP会把你的欺骗包过滤掉。虽然现在大多数的ISP不会对此进行限制。

-S

在一些情况下,nmap可能无法确定你的源地址(nmap会告诉你)。在这种情况下,可以使用这个选项给出你的IP地址。

在欺骗扫描时,也使用这个选项。使用这个选项可以让目标认为是其它的主机对自己进行扫描。

-e

告诉nmap使用哪个接口发送和接受数据包。nmap能够自动对此接口进行检测,如果无效就会告诉你。

-g

设置扫描的源端口。一些天真的防火墙和包过滤器的规则集允许源端口为DNS(53)或者FTP-DATA(20)的包通过和实现连接。显然,如果攻击者把源端口修改为20或者53,就可以摧毁防火墙的防护。在使用UDP扫描时,先使用53号端口;使用TCP扫描时,先使用20号端口。注意只有在能够使用这个端口进行扫描时,nmap才会使用这个端口。例如,如果你无法进行TCP扫描,nmap会自动改变源端口,即使你使用了-g选项。

对于一些扫描,使用这个选项会造成性能上的微小损失,因为我有时会保存关于特定源端口的一些有用的信息。

-r

告诉nmap不要打乱被扫描端口的顺序。

--randomize_hosts

使nmap在扫描之前,打乱每组扫描中的主机顺序,nmap每组可以扫描最多2048台主机。这样,可以使扫描更不容易被网络监视器发现,尤其和--scan_delay 选项组合使用,更能有效避免被发现。

-M

设置进行TCP connect()扫描时,最多使用多少个套接字进行并行的扫描。使用这个选项可以降低扫描速度,避免远程目标宕机。

参考资料:nmap- []说明

参考技术A TCP connect()扫描:这是最基本的TCP扫描方式。connect()是一种系统调用,由操作系统提供,用来打开一个连接。如果目标端口有程序监听,connect()就会成功返回,否则这个端口是不可达的。这项技术最大的优点是,你勿需root权限。任何UNIX用户都可以自由使用这个系统调用。这种扫描很容易被检测到,在目标主机的日志中会记录大批的连接请求以及错误信息

为啥 connect() 会给出 EADDRNOTAVAIL?

【中文标题】为啥 connect() 会给出 EADDRNOTAVAIL?【英文标题】:Why would connect() give EADDRNOTAVAIL?为什么 connect() 会给出 EADDRNOTAVAIL? 【发布时间】:2011-04-22 15:19:48 【问题描述】:

我的应用程序出现了一个似乎无法重现的故障。我有一个失败的 TCP 套接字连接,应用程序试图重新连接它。在尝试重新连接的第二次 connect() 调用中,我得到一个错误结果,错误结果为 errno == EADDRNOTAVAIL,connect() 的手册页表示:“本地计算机无法使用指定的地址。”

查看对connect()的调用,第二个参数似乎是错误所指的地址,但据我了解,这个参数是远程主机的TCP套接字地址,所以我很困惑关于引用本地机器的手册页。是不是我的本地机器上没有这个远程 TCP 套接字主机的地址?如果是这样,为什么会这样?它必须在连接失败之前第一次成功调用 connect() 并尝试重新连接并收到此错误。两次 connect() 的参数都是相同的。

如果我再次尝试调用 connect,如果我等待足够长的时间,这个错误是否会消失?如果不是,我应该如何尝试从这个失败中恢复?

【问题讨论】:

我在大型 Redis 集群中遇到了类似的问题。你的用例是什么? 【参考方案1】:

查看此链接

http://www.toptip.ca/2010/02/linux-eaddrnotavail-address-not.html

编辑:是的,我本来想添加更多,但由于紧急情况不得不删掉它

您在尝试重新连接之前是否关闭了套接字?关闭将告诉系统套接字对(ip/port)现在是空闲的。

这里还有一些额外的项目:

如果本地端口已经连接到给定的远程 IP 和端口(即,已经有相同的套接字对),您将收到此错误(请参阅下面的错误链接)。 绑定非本地套接字地址会产生此错误。如果机器的 IP 地址是 127.0.0.1 和 1.2.3.4,并且您尝试绑定到 1.2.3.5,则会出现此错误。 EADDRNOTAVAIL:指定的地址在远程机器上不可用或名称结构的地址字段全为零。

链接到与你类似的错误(答案接近底部)

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294599

您的套接字似乎基本上停留在 TCP 内部状态之一,添加重新连接延迟可能会解决您的问题,正如他们在该错误报告中所做的那样。

【讨论】:

【参考方案2】:

如果给定的端口无效,例如 0,也会发生这种情况。

【讨论】:

作为目标端口。如果它作为要绑定的本地端口提供,则它是有效的。【参考方案3】:

如果您不愿意更改可用的临时端口数量(如 David 所建议的那样),或者您需要的连接数超过了理论最大值,还有其他两种方法可以减少正在使用的端口数量。但是,它们在不同程度上违反了 TCP 标准,因此应谨慎使用。

第一种是开启SO_LINGER,超时时间为零,强制TCP堆栈发送RST数据包并刷新连接状态。但是有一个微妙之处:您应该在close 之前调用套接字文件描述符上的shutdown,这样您就有机会在RST 数据包之前发送FIN 数据包。所以代码看起来像:

shutdown(fd, SHUT_RDWR);
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_LINGER,
           (char *) &linger, sizeof(linger));
close(fd);

如果FIN 数据包与RST 数据包重新排序,服务器应该只会看到过早的连接重置。

请参阅TCP option SO_LINGER (zero) - when it's required 了解更多详情。 (在实验上,setsockopt 的设置位置似乎并不重要。)

第二个是使用SO_REUSEADDR 和显式bind(即使您是客户端),这将允许Linux 在您运行时重用临时端口,然后再等待。请注意,您必须bindINADDR_ANY 和端口0 一起使用,否则SO_REUSEADDR 将不受尊重。您的代码将类似于:

int opts = 1;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
         (char *) &opts, sizeof(int));

struct sockaddr_in listen_addr;
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0;
listen_addr.sin_addr.s_addr = INADDR_ANY;
// todo: test for error
bind(fd, (struct sockaddr *) &listen_addr, sizeof(listen_addr));

// todo: test for addr
// saddr is the struct sockaddr_in you're connecting to
connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));

这个选项不太好,因为您仍然会根据netstat -an | grep -e tcp -e udp | wc -l 使 TCP 连接的内部内核数据结构饱和。但是,在这种情况发生之前,您不会开始重用端口。

【讨论】:

SO_LINGER 设置为零解决了我的问题。谢谢。【参考方案4】:

我遇到了这个问题。我通过启用 tcp 时间戳解决了它。

根本原因:

    连接关闭后,连接将进入 TIME_WAIT 状态一段时间 时间。

    在此状态下,如果任何新连接具有相同的 IP 和 PORT, 如果在创建套接字期间未提供 SO_REUSEADDR,则套接字 bind() 将失败并出现错误 EADDRINUSE。

    但是即使在提供 SO_REUSEADDR 之后 sockect connect() 也可能 如果双方均未启用 tcp 时间戳,则失败并返回错误 EADDRNOTAVAIL。

解决方案: 请在客户端和服务器端启用 tcp 时间戳。

echo 1 > /proc/sys/net/ipv4/tcp_timestamps

启用 tcp_timestamp 的原因:

当我们启用 tcp_tw_reuse 时,处于 TIME_WAIT 状态的套接字可以在过期之前被使用,内核会尝试确保没有关于 TCP 序列号的冲突。如果我们启用 tcp_timestamps,它将确保不会发生这些冲突。但是,我们需要在两端启用 TCP 时间戳。血淋淋的细节见 tcp_twsk_unique 的定义。

参考: https://serverfault.com/questions/342741/what-are-the-ramifications-of-setting-tcp-tw-recycle-reuse-to-1

【讨论】:

【参考方案5】:

要检查的另一件事是接口是否已启动。我最近在使用网络命名空间时对此感到困惑,因为它似乎创建一个新的网络命名空间会产生一个完全独立的环回接口,但不会带来它(至少,对于 Debian wheezy 的事物版本)。这让我有一段时间没有想到,因为人们通常不会认为环回是关闭的。

【讨论】:

以上是关于请给出TCP connect()这个函数的所有参数及其解释?的主要内容,如果未能解决你的问题,请参考以下文章

UNIX网络编程卷1 时间获取程序client TCP 使用非堵塞connect

为啥 connect() 会给出 EADDRNOTAVAIL?

connect函数中参数

TCP客户端 服务端详细代码

通过端口 1433 连接到主机 localhost 的 TCP/IP 连接失败。错误:“connect timed out。请验证连接属性,并

tcp_connect函数