Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

网络连接过程分析 #35

Open
chenpengcong opened this issue Feb 5, 2022 · 0 comments
Open

网络连接过程分析 #35

chenpengcong opened this issue Feb 5, 2022 · 0 comments

Comments

@chenpengcong
Copy link
Owner

chenpengcong commented Feb 5, 2022

本文介绍我们平常上网时计算机是如何接入网络的,过程涉及到哪些协议,主要分析流程,对协议本身不会过多探究。

为了可以灵活地配置网络,这里基于Virtualbox搭建一个局域网络用于模拟真实环境,最终搭建的网络拓扑如下

network-topology

VM2模拟我们上网使用的计算机

VM1模拟路由器,上面同时运行着DHCP服务

网络搭建

本文的VM1和VM2均使用debian10系统

VM2

网卡配置

分配一个网卡,选择内部网络(Internal Network)

启动系统后先不配置网卡,网卡配置文件/etc/network/interfaces保持默认内容即可

不直接配置网卡使用DHCP是为了避免系统启动后自动完成IP的获取,导致我们无法捕获首次DHCP交互流量

VM1

网卡配置

分配两个网卡

  • 网卡1选择桥接网卡(Bridged Adapter)

  • 网卡2选择内部网络

启动系统后分别配置两个网卡的网络

  • 配置网卡1使用DHCP协议动态获取IP,该网卡用于连接外网

  • 配置网卡2使用静态地址192.168.23.1,掩码255.255.255.0,该网卡用于连接内网

网卡1和网卡2的名称可以使用ifconfig -a查看,通过MAC地址可以辨别网卡1和网卡2

本文网卡1名称为enp0s3,网卡2名称为enp0s8

修改后的/etc/network/interfaces文件内容如下

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback
# The primary network interface
auto enp0s3 # 网卡1
iface enp0s3 inet dhcp
auto enp0s8 # 网卡2
iface enp0s8 inet static 
	address 192.168.23.1
	netmask 255.255.255.0

然后重启网络

$ service networking restart

在我的网络环境下桥接模式的网卡enp0s3被分配的IP为192.168.43.237

配置NAT

接下来使用iptables配置NAT,以实现VM2可以通过VM1访问外网

$ iptables -t nat -A POSTROUTING -s 192.168.23.0/24 -o enp0s3 -j SNAT --to-source 192.168.43.237

注意该配置重启后会失效

该配置表示将来自192.168.23.0/24的网络请求从网卡enp0s3发出去,并且将源IP改成192.168.43.237

同时还需开启IP转发,以支持将enp0s8网卡收到的内网流量从enp0s3网卡发送出去

$ vim /etc/sysctl.conf # 配置net.ipv4.ip_forward=1
$ sysctl -p

NAT相关知识可以参考鸟哥的私房菜 9.5 NAT服务器的设定

配置DHCP Server

安装isc-dhcp-server

$ apt install isc-dhcp-server 

配置DHCP服务,修改/etc/default/isc-dhcp-server文件如下,这里只关注IPv4

# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf

# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
DHCPDv4_PID=/var/run/dhcpd.pid
#DHCPDv6_PID=/var/run/dhcpd6.pid

# Additional options to start dhcpd with.
#	Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
#OPTIONS=""

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#	Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="enp0s8"
#INTERFACESv6=""

修改/etc/dhcp/dhcpd.conf文件如下,基本保持原内容不变,增加一个subnet配置

# option definitions common to all supported networks...
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

default-lease-time 600;
max-lease-time 7200;

# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

subnet 192.168.23.0 netmask 255.255.255.0 {
	option routers 192.168.23.1;
	option domain-name-servers 192.168.43.1;# 这里与宿主机(host)的DNS保持一致
	range 192.168.23.100 192.168.23.200;
}

然后启动DHCP Server

$ service isc-dhcp-server start

流量捕获

为了尽可能减少其他网络流量对我们分析造成干扰,获得相对"干净"的流量,可以参考下述操作步骤

  1. 启动VM1,确保DHCP Server正常启动,IP Forward打开,NAT成功配置

  2. 启动VM2,打开两个Shell

    打开多个shell这里我使用了screen工具,参考How to split the terminal into more than one "view"

    首先在Shell1操作

    $ ifconfig enp0s3 up # 激活网卡enp0s3,否则tcpdump工具无法捕获该网卡流量
    $ tcpdump -i enp0s3 -w enp0s3.pcap # 启动tcpdump捕获网卡enp0s3的流量
    

    接下来在Shell2中操作

    $ dhclient enp0s3 # 让网卡enp0s3动态获取IP
    $ curl www.baidu.com # 访问外网
    

​ 最后ctrl+c停止shell1中的tcpdump程序即可

得到流量包enp0s3.pcap

流量分析

分析得到的流量包enp0s3.pcap,整理出交互流程如下

network-flow

建议搭配《计算机网络-自顶向下方法 第7版》的6.7章节"回顾:Web页面请求的历程"中的描述来分析这个流程,有很多共同之处,相比书中的理论知识,本文还使用了命令的实际输出结果来对理论进行验证

值得注意的知识点:

  • DHCP Offer/Ack可能是单播也可能是广播,具体由DCHP Discover请求中的Bootp flags指示,在RFC2131中相关描述如下

    A client that cannot receive unicast IP datagrams until its protocol software has been configured with an IP address SHOULD set the BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or DHCPREQUEST messages that client sends. The BROADCAST bit will provide a hint to the DHCP server and BOOTP relay agent to broadcast any messages to the client on the client's subnet. A client that can receive unicast IP datagrams before its protocol software has been configured SHOULD clear the BROADCAST bit to 0. The BOOTP clarifications document discusses the ramifications of the use of the BROADCAST bit [21].

    A server or relay agent sending or relaying a DHCP message directly to a DHCP client (i.e., not to a relay agent specified in the 'giaddr' field) SHOULD examine the BROADCAST bit in the 'flags' field. If this bit is set to 1, the DHCP message SHOULD be sent as an IP broadcast using an IP broadcast address (preferably 0xffffffff) as the IP destination address and the link-layer broadcast address as the link-layer destination address. If the BROADCAST bit is cleared to 0, the message SHOULD be sent as an IP unicast to the IP address specified in the 'yiaddr' field and the link-layer address specified in the 'chaddr' field.If unicasting is not possible, the message MAY be sent as an IP broadcast using an IP broadcast address (preferably 0xffffffff) as the IP destination address and the link- layer broadcast address as the link-layer destination address.

  • DHCP offer 报文到底是单播还是广播问题中,提问者从回答中得知DHCP Offer之所以能正确设置目标MAC地址是因为客户端的DHCP Discover请求中包含了chaddr(Client Hardware Address),然后提问者又抛出了个问题

    虽然 discover 报文里包含了我的 Mac 地址,但是这是应用层的内容,难道响应封装帧的时候把应用层的信息拿过来用了?但是好像不太合理啊

    这里个人理解是DHCP Server在实现的过程中使用的较为底层的API,直接构造的链路层报文,经过查阅也确实能做到,参见Sending raw Ethernet packets from a specific interface in C on Linux,当然要最终确认得去看isc-dhcp-server的源码了,这里就不深究了。

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant