本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。

作者:gfree.wind@gmail.com

博客:linuxfocus.blog.chinaunix.net

一般情况下,我们使用raw socket都是用于发送icmp包或者自己定义的包。最近我想用raw socket

自己去创建TCP的包,并完成3次握手。

在这个过程中,发现了几个问题:

1. 发现收不到对端返回的ACK,但是通过tcpdump却可以看到。这个通过修改创建socket的API参数得以纠正。

原来创建socket使用如下参数s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)。因为linux的raw socket不会把

不会把UDP和TCP的分组传递给任何原始套接口。——见《UNIX网络编程》28.3.

所以为了读到ACK包,我们创建的raw socket需要建立在数据链路层上。

s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))

这样该socket就可以读取到所有的数据包。当然这样的数据包无疑是非常庞大的,那么我们可以

使用bind和connect来过滤数据包。bind可以指定本地的IP和端口,connect可以指定对端的IP和端口。

2. 在修改完创建socket的API,我发现还有一个问题,到现在依然没有找到合适的解决方法。

通过链路层的raw socket,我们可以收到对端的ACK。但是因为linux内核也会处理TCP的握手过程,

所以,当它收到ACK的时候,会认为这是一个非法包,会直接发送一个RST给对端。这样我们拿到了这个ACK,

也没有实际的用处了——因为这个连接已经被RST了。

我想,内核之所以会直接发送RST,也许是因为我们创建的是raw socket,但是发送的确是TCP包,

当对端返回ACK时,内核根本不认为我们已经打开了这个TCP端口,所以会直接RST掉这个连接。

那么问题就在于,我们如何告诉内核,我们打开了TCP的这个端口。

我想过一个方法,除了一个raw socket,再创建一个真正的TCP socket。但是细想起来,这条路应该行不通。

在网上搜了半天,总算找到一个比较详细的解释了。原因给我猜想的相差不远,当我们使用raw

socket来发送sync包时,内核的TCP协议栈并不知道你发送了sync包,所以当对端返回SYNC/ACK时,内核首先要处理这个包,发现它是一

个SYNC/ACK,然而协议栈却不知道前面的sync,所以就认为这个包是非法的,于是就会发送RST来中止连接。

原文如下:

This is one of the most frequently asked question by someone who is

experimenting with raw sockets and TCP/IP. It is known that the

'IP_HDRINCL' socket option allows you to include the IP header along

with the data. Since TCP encapsulates the IP header, we can also build

a TCP packet and send it over a network. But the problem is, a TCP

connection can never be established this way. The scenario is as

follows:

A TCP connection is always made by a three-way handshake.

So, initially you send a 'SYN' packet to the remote machine. If it is

actively listening on the port, you get a 'SYN/ACK' packet. So far so

good. But before you can respond, your machine sends an 'ACK/RST'

packet and connection attempt is ended. For the connection to be

complete, instead of the 'RST' packet, your machine should be sending

an 'ACK' to the remote machine.

The difference lies where the

connection is exactly made. Although the programs are communicating

after the connection is complete, the TCP connection is never between

two programs but rather between the TCP stacks of the two machines.

Here 'stack' means a layer of programs that communicates between each

other. TCP stack stands for the protocol driver or the actual network

transport protocol. Now lets look at exactly what happens when you send

a 'SYN' packet...

Since you are using raw sockets ('SOCK_RAW') and

not TCP/Stream sockets ('SOCK_STREAM') the TCP stack has no information

about what you are doing at program level. And since the 'IP_HDRINCL'

allows you to build any type of IP packet and send it along with the

data, you can build a 'SYN' packet and send it to the TCP server

program which is actively listening. But the point is that the 'SYN'

packet is being sent from your program and not the stack. In other

words the TCP stack of your machine has no idea how of sending the

'SYN' packet.

On the other side the 'SYN' packet is received by the

stack at the remote machine and not exactly by the program. As with the

case of the arrival of any 'SYN' packet, the stack at the remote

machine responds with a 'SYN/ACK' packet. This packet is now received

by the TCP stack of your machine. In other words, the incoming TCP

packet ('SYN/ACK') will be processed by the stack. Since it has no

information of the previous sent 'SYN' packet, it responds with a 'RST'

packet, as in the case of any improper or unacceptable packet for a

connection.

So the difference between sending and receiving a TCP

packet using raw sockets is, the former is not processed while the

latter is processed by the TCP stack of your machine.

该解释来自于,

感谢Mr Andreas Masur 和Mr Mathew Joy. Thanks Mr Andreas Masur and Mr Mathew Joy.

作者:gfree.wind@gmail.com

linux raw限制端口访出,使用Linux raw socket时需要注意的一些问题相关推荐

  1. linux 更改ssh端口_如何在Linux中更改SSH端口-简易指南

    linux 更改ssh端口 The default port on SSH is 22. But for security reasons, it's a good idea to change SS ...

  2. linux服务器80端口无法访问,Telnet linux服务器80端口时通时不通

    Telnet linux服务器80端口时通时不通 一.概述 两台linux服务器之间互相通信没有问题,但是开发人员需要Telnet我们服务器的80端口,现象就是时通时不通. 二.分析 我们服务器用的是 ...

  3. linux下apache端口被占用,【linux】下Apache无法启动(8080端口被占用)

    Linux下8080端口被占用,apache无法启动. 打开终端输入netstat -lnp|grep 8080 发现竟然是tcp6 占用里,因此ipv6启用占用了端口. 1.打开/etc/sysct ...

  4. 在linux中查看端口信息,怎样在 Linux 上查看某个端口的相关信息?

    C#用扩展方法进行自动生成添加删除对象转换的功能 public static class ExtendedModel { #region 实体类的增删改查 #region 添加 public stat ...

  5. linux 开放1701端口,长连接及Linux 查看长连接端口

    长连接及Linux 查看长连接端口 [日期:2009-02-10] 来源:Linux公社 作者:Linuxidc [字体:大 中 小] unix  3      [ ]         流       ...

  6. linux 查看usb端口_linux开发:Linux下查看端口占用

    怎么查看linux系统中已经被占用的端口?下面我就统一给大家解释一下. 提到端口,那首先来回顾端口定义,为了区分一台主机接收到的数据包应该转交给哪个任务来进行处理,使用端口号来区别:我们知道TCP端口 ...

  7. linux怎么查端口是否被占用,LINUX中如何查看某个端口是否被占用

    之前查询端口是否被占用一直搞不明白,问了好多人,终于搞懂了,现在总结下: 1.netstat  -anp  |grep   端口号 如下,我以3306为例,netstat  -anp  |grep   ...

  8. linux中查看端口号使用情况

    目录 linux中查看端口号使用情况 netstat linux中查看端口号使用情况 linux中查看端口号使用情况使用netstat命令 命令如下: netstat -tunpl | grep 端口 ...

  9. Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序

    文章目录: 1 linux查看那端口监听情况 2 Linux查看某个端口对应的进程号和程序 1 linux查看那端口监听情况 linux中可以使用netstat命令查看端口监听情况,首先来看一下该命令 ...

最新文章

  1. 软件工程——求二维数组所有子矩阵的和的最大值
  2. 筱玛爱游戏——线性基
  3. java ora-12505_Oracle SQL Developer连接报错(ORA-12505)的解决方案(两种)
  4. CF1516E. Baby Ehab Plays with Permutations(组合数学)
  5. cocos怎么把res文件夹放服务器上,cocos2d 三合一跑胡子房卡+服务器组件+后台控制+安装教程+棋牌完整源码...
  6. 获取另一个驱动的设备结构体_字符设备驱动的另一种写法
  7. 95-18-015-配置-AbstractBootstrapConfig
  8. 一个高效简洁的Struts分页方法
  9. python hello world程序编写_自动编写Python程序的神器,Python 之父都发声力挺
  10. python写斗地主游戏_基于python的简单斗地主实现-Go语言中文社区
  11. react-ssr之路由配置
  12. 百合佳缘伐谋、珍爱网伐交、伊对伐兵
  13. 怎样用计算机筛选,教您Excel中筛选功能怎么用
  14. VIN码识别又叫车架号识别,OCR技术深度应用
  15. 在Ubuntu上安装NTL库以及编译测试
  16. DBCO-PEG4-alcohol CAS:1416711-60-8 二苯基环辛炔-四聚乙二醇-乙醇
  17. ubuntu安装过程中提示: the path is not vaild path to the gcc binary等gcc路径不对和kernel不存在?
  18. Webview 打开qq聊天窗口,申请进群
  19. ORA-29702错误解决
  20. (转)BT下载不死!Magnet(磁力链接)开创网络BT2.0时代!!

热门文章

  1. Java学习笔记(7)——输入输出
  2. Go学习笔记—Go并发基础
  3. 2. with check option能起什么作用?_面部毛孔粗大,有什么拯救的方法吗?
  4. java resourcebundle_Java - Properties和ResourceBundle类学习
  5. 电脑技巧:电脑安装操作系统、重装系统常见的问题解决方法!
  6. 收集sqlite常见问题
  7. MYSQL数据损坏修复方法
  8. 更新系统后魔兽世界无法连接至服务器,《魔兽世界:熊猫人之谜》5.0launcher更新无法连接服务器解决方法...
  9. mrsql查询第二高的成绩_mysql-查找用户的最高分数和相关的详细信息
  10. 金三银四的腾讯、阿里、​字节等大厂前端社招面经