往某ip地址发数据时,用户在应用层写下的一串ip地址和负载打包成数据报然后发给网络层,但是应用层数据报是没有ip地址信息的,这个数据报往网络层传递,那网络层帧ip首部的ip地址来源是什么?不可能随便加个别的地址放在首部吧?还是说应用层往网络层传数据报的时候会添加额外的ip地址字段,网络层根据这个信息填写ip首部?
★问题:用户要访问一个目标,不管写的目的地址是域名还是ip,这个信息总归要往网络层传达才能作为网络层封装ip地址字段的依据,应用层从哪告诉网络层的?
假设用户访问的公众号 :
https://mp.weixin.qq.com/
无论是通过APP还是浏览器,第一步DNS域名解析,通过调用getaddrinfo(),得到的返回值如上图所示。
由于主机没有配置IPv6地址,故挑选了一个IPv4=101.89.49.42地址使用。
到目前为止,client软件已经具有必要的服务器信息,如下所示:
Remote IP =101.89.49.42
Remote Port =443
Transport = TCP
Transport Layer Security =TLS
下一步,Client软件需要调用socket(),创建一切必要的数据结构。在Linux操作系统主要创建 File、Socket、TCP_Sock。这三者是怎么用关系网连接起来的呢?
File->private_data,指向Socket结构体在内存中存放位置。
Socket->sk , 指向TCP_Sock结构体在内存中存放位置。
问题来了,如何通过File找到TCP_Sock?
File->private_data->sk
简单地说,通过这三者中的任何一个人,都可以找到另外两个人。不久前的公众号文章写过socket关系网,其实就是描述这种现象。
当socket调用成功,不能直接告诉你它们的内存存放位置,而是返回一个整数,比如3,这个返回的整数也有一个极好听的名字File Descriptor,简称FD。
接下来Client需要与服务器用connect()建立TCP连接了。
这个connect需要2个必选项输入参数,分别是:
FD=3
Remote.address =101.89.49.42,Remote.port =443
真实的调用应该是这样的 connect(FD, &remote) ==connect(3, &remote)
问题又来了,内核如何找到上文的三个人?
current->files->fdt->fd[fd]
将FD=3代入上式,可得:
current->files->fdt->fd[3] 指向File结构体。
current->files->fdt->fd[3]->private_data指向Socket结构体。
current->files->fdt->fd[3]->private_data->sk指向TCP_Sock结构体。
找到TCP_Sock,就可以将remote参数传入到TCP_Sock成员变量,即服务器的IP =101.89.49.42, 端口号 =443。
current是什么?
通俗地说,它指向client用户进程的(task_struct)。无论是进程(process) 还是线程(thread),在Linux上都有一个对应的task_struct结构体。
CPU凭借current,可以找到以上三个人,还可以找到关系网中的成员。以上3个人尽管很关键,但是要把TCP报文发出去远远不够。
有了TCP_Sock就可以发TCP SYN报文,建立TCP连接了。
构建一个超级大的struct sk_buff实例 ,简称skb。这个skb有两部分,meta-data、data部分,meta-data有各种指针指向TCP header、IP Header 、Ethernet Header以及packet存放的位置,指向data。
skb里还携带这众多关系网,题主最关心的可能是:
skb->sk指向上文的TCP_Sock结构体。
接下来就简单了,TCP填充自己的字段,并选择一个随机端口作为源端口,假设为Source Port=58888,并记录在TCP_Sock里。然后调用IP接口函数,输入的参数skb。
IP接口函数,立马可以根据skb->sk得到要连接的服务器的IP地址、端口。如果忘记如何得到,再阅读一遍文章。
IP接口函数,查询路由表,得到从哪个物理接口离开。由于client没有提供源IP,就用查询到的物理接口IP。假设查询的接口ens33=10.1.1.2,那么就使用它作为源IP地址。
还需要将查询到的路由entry,记录在TCP_Sock里,下次再发packet,就用这个路由entry。
调用ens33对应的output函数发送,output函数内部可能还要ARP查询。查完之后调用网卡的driver函数,然后driver函数负责将skb->data搬运到网卡,并由网卡发送出去。
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...