【大牛说】
码大牛,成长于传智播客和黑马程序员的专家型顾问。大牛老师从今天开始推出一个固定栏目,推出关于技术、教学话题的干货和想法。每周二、周四,大牛老师会在微信公众号(boxuegu)和QQ(2011168841)空间同步更新。
经常在电影里看到超级黑客高手,在电脑前轻松“黑”进别人的安全系统的场景,纯熟自如地输入一大堆复杂的代码,瞬间破解完成。那装逼指数,绝对满分。直到接触了一点计算机底层的知识,了解了一点网络安全,才知道黑客入侵的第一屏障就是原始套接字。
聊到了套接字,就和大家说一说
老师和大牛聊天的时候,反馈对TCP/UDP已经非常了解了,但是对原始套接字的原理和规则还是比较陌生。大牛又接连问了几位老师,普遍都是这样的反馈。
所以,大牛在这里针对“原始套接字”给大家简单补上一课,其实原始套接字不但广泛应用于高级网络编程,也是一种广泛的黑客手段。著名的网络sniffer(一种基于被动侦听原理的网络分析方式)、拒绝服务攻击(DOS)、IP欺骗等都可以通过原始套接字实现。需要注意的是,必须在管理员权限下才能使用原始套接字。OK闲话不多说,进入正题。
经典的“三次握手”
先简单复习一下TCP报文的格式。
从上图我们分析一次,TCP的3次握手情况:
(1) 第一次握手:建立连接时,客户端A发送SYN包(SEQ_NUMBER=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2) 第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK_NUMBER=j+1),同时自己也发送一个SYN包(SEQ_NUMBER=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3) 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK_NUMBER=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
至此3次握手结束,TCP通路就建立起来了,然后客户端与服务器开始交互数据。
上面的TCP的3次握手流程是不是很熟悉?
浅析原始套接字
原始套接字(SOCK_RAW)与标准套接字(SOCK_STREAM、SOCK_DGRAM)的区别在于原始套接字直接置“根”于操作系统网络核心(NetworkCore),而 SOCK_STREAM、SOCK_DGRAM 则“悬浮”于 TCP 和 UDP 协议的外围。流式套接字只能收发 TCP 协议的数据,数据报套接字只能收发UDP 协议的数据,原始套接字可以收发内核没有处理(网卡上原生态)的数据包。
1. 原始套接字的创建:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ether.h>// ETH_P_ALL
int socket(int family, int type,int protocol);
功能:创建套接字
参数:
family:协议族,创建原始套接字写 PF_PACKET
type: 套接字类,这里写SOCK_RAW
protocol:协议类别,指定可以接收或发送的数据包类型,不能写 “0”,取值如下,注意,传参时需要用 htons()进行字节序转换。
ETH_P_IP:IPV4数据包
ETH_P_ARP:ARP数据包
ETH_P_ALL:任何协议类型的数据包
返回值:
成功(>0):套接字,这里为链路层的套接字
失败(<0):出错
2. 获取链路层的数据包:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t
nbytes, int flags, structsockaddr *from, socklen_t *addrlen);
功能:获取链路层的数据包
参数:
sockfd : 原始套接字
buf:接收数据缓冲区
nbytes : 接收数据缓冲区的大小
flags:套接字标志(常为0)
from:这里没有用,写 NULL
addrlen:这里没有用,写NULL
返回值:
成功:接收到的字符数
失败: - 1
3. 发送自定义的数据包:
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, constvoid *buf, size_t nbytes, int flags, const struct sockaddr *to, socklen_taddrlen);
功能:发送自定义的数据包
参数:
sockfd:原始套接字
buf:发送数据缓冲区
nbytes : 发送数据缓冲区的大小
flags:一般为 0
to:本机网络接口,指发送的数据应该从本机的哪个网卡出去
addrlen:to 所指向内容的长度
返回值:
成功:发送数据的字符数
失败: - 1
4. 获取本机网络接口:
#include <net/if.h>//struct ifreq
#include <sys/ioctl.h> //ioctl、SIOCGIFADDR
#include<netpacket/packet.h> // struct sockaddr_ll
struct sockaddr_ll sll; //原始套接字地址结构
struct ifreq ethreq; //网络接口地址
strncpy(ethreq.ifr_name,"ens33", IFNAMSIZ); //指定网卡名称
写到这,大家对原始套接字的使用方法以及TCP/IP协议结构原理等知识有一个基本的认识。原始套接字要学的东西很深,有这方面教学需要或者对网络安全感兴趣的老师可以继续研究,但是千万不要利用原始套接字来做一名黑客哦!
教学好助手(boxuegu)
教IT、学IT都会关注的公众号
定期推送IT技术、教学干货和教师话题思考
我要评论