原始套接字SOCK_RAW

news/2024/5/17 18:20:29 标签: socket, tcp, stream, 网络, 编程, domain

实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM)。而这些数据包都是由系统提供的协议栈实现,用户只需要填充应用层报文即可,由系统完成底层报文头的填充并发送。然而在某些情况下需要执行更底层的操作,比如修改报文头、避开系统协议栈等。这个时候就需要使用其他的方式来实现。

 

一 原始套接字

原始套接字(SOCK_RAW)是一种不同于SOCK_STREAMSOCK_DGRAM的套接字,它实现于系统核心。然而,原始套接字能做什么呢?首先来说,普通的套接字无法处理ICMPIGMP网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。总体来说,SOCK_RAW可以处理普通的网络报文之外,还可以处理一些特殊协议报文以及操作IP层及其以上的数据。

既然SOCK_RAW有以上特性,所以在某些处理流程上它区别于普通套接字。

·  若设置IP_HDRINCL选项,SOCK_RAW可以操作IP头数据(也就是用户需用填充IP头及其以上的payload);否则SOCK_RAW无法操作IP头数据

·  端口对于SOCK_RAW而言没有任何意义

·  如果使用bind函数绑定本地IP,那么如果IP_HDRINCL未设置,则用此IP填充源IP地址;若不调用bind则将源IP地址设置为外出接口的主IP地址

·  如果使用connect函数设置目标IP,则可以使用send或者write函数发送报文,而不需要使用sendto函数

·  内核处理流程:

·   接收到的TCPUDP分组不会传递给任何SOCK_RAW

·  ICMPIGMP报文分组传递给SOCK_RAW

·  内核不识别的IP报文传递给SOCK_RAW

·  SOCK_RAW是否接收报文:

·      Protocol指定类型需要匹配,否则不传递给该SOCK_RAW

·       如果使用bind函数绑定了源IP,则报文目的IP必须和绑定的IP匹配,否则不传递给该SOCK_RAW

·       如果使用connect函数绑定了目的IP,则报文源IP必须和指定的IP匹配,否则不传递给该SOCK_RAW 


综上所述,原始套接字处理的只是IP层及其以上的数据,比如实现SYN FLOOD攻击、处理PING报文等。当需要操作更底层的数据的时候,就需要采用其他的方式。

二 链路层处理报文

如果需要从链路层处理报文,那么就需要采用更加底层的套接字。还是先看下套接字函数的原型吧:

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

这个函数中,domain表示协议簇,type表示套接字类型,而protocol表示的是处理的协议类型。在Linux下提供了多种底层套接字。下面分别进行简单介绍。

1 PF_INET协议簇

通过PF_INET可以构造原始套接字,如下所示:

int fd = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);

正如前面所讲的,它工作在IP层及其以上各层协议上(当然是在使用IP_HDRINCL选项之后才能操作IP层数据啦),但是这种套接字无法接收从本地发送出去的报文。而使用SOCK_PACKET类型的套接字,则可以操作链路层数据了:

int fd = socket (PF_INET, SOCK_PACKET, IPPROTO_TCP);

不过据说这种方式存在一定的缺陷,而且也不能保证后续版本的系统上一定支持这种方式,因此不推荐使用

2 PF_PACKET协议簇

PF_PACKET协议簇是用来取代SOCK_PACKET的一种编程接口。作为一种协议簇,它可以对应两种不同的套接字类型:SOCK_RAWSOCK_DGRAM。当使用SOCK_RAW时,用户操作链路层数据,但是如果使用后者,则由系统处理链路层协议头。这种套接字支持四种协议(ETH_P_IPETH_P_ARPETH_P_RARPETH_P_ALL)(未确认)

int fd = socket (PF_PACKET, SOCK_RAW, IPPROTO_TCP);

int fd = socket (PF_PACKET, SOCK_DGRAM, IPPROTO_TCP);

3 NETLINK协议簇

这种方式是用户模式和kernelIP网络配置之间的推荐接口


 

综上所述,真正能够实现操作链路层数据的只有三种方式:

int fd = socket (PF_INET, SOCK_PACKET, IPPROTO_TCP);

int fd = socket (PF_PACKET, SOCK_RAW, IPPROTO_TCP);

int fd = socket (PF_PACKET, SOCK_DGRAM, IPPROTO_TCP);




http://www.niftyadmin.cn/n/1116285.html

相关文章

Head First Python 第一章 初始Python

1.安装python解释器和ide&#xff0c;这里选择pycharm&#xff0c;配好环境 2.列表的例子&#xff1a; python没有数组&#xff0c;只有元组合列表 列表例子如下 movies["titanic","the big bang theory"]print (movies[0]) 列表支持insert&#xff0c;pop…

探寻新的治疗方法,研究人员用VR可视化DNA结构

研究团队希望借助VR分析DNA的状态来探寻疾病的根源&#xff0c;找到新的治疗方案。 虚拟现实不仅可以广泛用于商业&#xff0c;还能助力解决一些学术难题。继用于论证物理学引力波证明难题后&#xff0c;又一家大学将VR融入了学术研究&#xff0c;这一次是探究生物科技。 据悉…

go 学习 5 接口

接口类型 interface 是由一组方法签名定义的集合。 接口类型的值可以保存任何实现了这些方法的值。 在内部&#xff0c;接口值可以看做包含值和具体类型的元组&#xff1a;(value, type) type I interface { M()}type T struct { S string}func (t *T) M() { fmt.Prin…

触碰未来的知识——云计算与大数据的关系

当你在淘宝购物时搜索到想要的商品&#xff0c;同时会看到一样非同类型的商品被推荐到眼前&#xff0c;恰巧也是你想要或者正需要购买的&#xff0c;这样神奇的经历源于前几年开始火起来的一项技术——大数据。我们也常常看到“云计算的发展推动了大数据产业的发展”等类似新闻…

Iovec,Msghdr

msghdr and cmsghdr 证书可以作为通信中所接收的附属数据的一部分而接收。附属数据对于通常数据来说是补充或是从属。这就引出需要在这里强调的几点问题&#xff1a; 证书是作为附属数据的一部分而接收的。 附属数据必须是补充通常数据的(他不可以独立传送)。 附属数据也可以包…

JavaScript后门深层分析

路人甲 2016/01/12 10:410x00 背景[email protected]JavaScript BackDoor中提到了利用rundll32.exe执行一段JavaScript代码即可反弹一个Http Shell&#xff0c;这里将之前看到的对其原理进行分析的文章翻译和大家分享。links: thisissecurity.net/2014/08/20/…最近&#xff0…

Shell 获取Shell所在目录

SHELL_PATH$(cd "$(dirname "$0")";pwd) echo $SHELL_PATH

IOS UI学习 UITableView ----- UITableViewDelegate

第一篇是关于UITableView的简单介绍以及UItableView 的 UITableViewDatasource 协议方法 那么这一篇这是关于 UITableView 的另一个代理 UITableViewDelegate的一些协议方法 设置每一个cell的高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSI…