初探网络与部署

234 阅读11分钟

网络接入

路由发包原理:

  • 同网段:配置网段即可默认添加静态路由。获取对端MAC直接发包

image.png

Note: 同网段并不一定都是通过物理设备连接的,也可能是通过上层的虚拟网络定义的同网段。

  • 跨网段:配置网关路由。获取网关MAC地址发包

    路由一定是对称的吗?

    路由是网状的,不一定是对称的

ARP协议

  • 逻辑同网段才能发送ARP

  • ARP请求广播,ARP应答单播

  • 代理ARP

  • 免费ARP

免费 ARP 报文与普通 ARP 请求报文的区别在于报文中的目标 IP 地址。普通 ARP 报文中的目标 IP 地址是其他主机的 IP 地址;而免费 ARP 的请求报文中,目标 IP 地址是自己的 IP 地址。

免费ARP有以下 3 个作用:

  • 该类型报文起到一个宣告作用。它以广播的形式将数据包发送出去,不需要得到回应,只为了告诉其他计算机自己的 IP 地址和 MAC 地址。
  • 可用于检测 IP 地址冲突。当一台主机发送了免费 ARP 请求报文后,如果收到了 ARP 响应报文,则说明网络内已经存在使用该 IP 地址的主机。
  • 可用于更新其他主机的 ARP 缓存表。如果该主机更换了网卡,而其他主机的 ARP 缓存表仍然保留着原来的 MAC 地址。这时,可以发送免费的 ARP 数据包。其他主机收到该数据包后,将更新 ARP 缓存表,将原来的 MAC 地址替换为新的 MAC 地址。

IP协议

  • MAC地址能够代替IP地址吗?

    MAC地址是数据链路层使用的地址,它也能唯一地确定一台主机在网络中的位置。但是它没有一种办法很好地区分不同的网络。

    MAC地址一共有48bit,分为两部分,前24bit是厂商代码,后24bit是厂家自己分配的。假如我们认为MAC地址可以区分不同的网络的话,那只能是使用厂商代码来区分不同的网络,也就是说使用同一个厂商生产的网卡的主机或者网络设备,就是属于同一个网络。举个例子,比如说企业A使用了思科的网络设备,企业B也使用了思科的网络设备,那这两家企业就属于同一个网络了。现实中这种情况是不可能的。

NAT

  • 多个内网客户端访问同一个目标地址+端口,源端口恰好一样,会冲突吗?

    NAPT同时映射IP地址和端口号:来自不同内部地址的数据报的源地址可以映射到同一外部地址,但它们的端口号被转换为该地址的不同端口号,因而仍然能够共享同一地址,也就是“私有地址+端口号”与“公网IP地址+端口号”之间的转换。

网络传输

以kernel为例 image.png

1、 DNS请求 - 域名映射ip

客户端发送递归请求,递归DNS服务器进行迭代请求。

image.png

DNS协议通过UDP进行传输。

UDP协议结构:

image.png

UDP怎么保证协议可靠?

2、TCP连接

image.png

拔了网线,TCP连接会断开吗?

针对这个问题,要分场景来讨论:

  • 拔掉网线后,有数据传输;

在客户端拔掉网线后,服务端向客户端发送的数据报文会得不到任何的响应,在等待一定时长后,服务端就会触发超时重传机制,重传未得到响应的数据报文。

如果在服务端重传报文的过程中,客户端刚好把网线插回去了,由于拔掉网线并不会改变客户端的 TCP 连接状态,并且还是处于 ESTABLISHED 状态,所以这时客户端是可以正常接收服务端发来的数据报文的,然后客户端就会回 ACK 响应报文。

此时,客户端和服务端的 TCP 连接依然存在的,就感觉什么事情都没有发生。

但是,如果如果在服务端重传报文的过程中,客户端一直没有将网线插回去,服务端超时重传报文的次数达到一定阈值后,内核就会判定出该 TCP 有问题,然后通过 Socket 接口告诉应用程序该 TCP 连接出问题了,于是服务端的 TCP 连接就会断开。

而等客户端插回网线后,如果客户端向服务端发送了数据,由于服务端已经没有与客户端相同四元祖的 TCP 连接了,因此服务端内核就会回复 RST 报文,客户端收到后就会释放该 TCP 连接。

此时,客户端和服务端的 TCP 连接都已经断开了。

  • 拔掉网线后,没有数据传输;

针对拔掉网线后,没有数据传输的场景,还得看是否开启了 TCP keepalive 机制 (TCP 保活机制)。

如果没有开启 TCP keepalive 机制,在客户端拔掉网线后,并且双方都没有进行数据传输,那么客户端和服务端的 TCP 连接将会一直保持存在。

而如果开启了 TCP keepalive 机制,在客户端拔掉网线后,即使双方都没有进行数据传输,在持续一段时间后,TCP 就会发送探测报文:

  • 如果对端是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
  • 如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡

所以,TCP 保活机制可以在双方没有数据交互的情况,通过探测报文,来确定对方的 TCP 连接是否存活。

TCP keepalive 是 TCP 层(内核态)  实现的,它是给所有基于 TCP 传输协议的程序一个兜底的方案。

实际上,我们应用层可以自己实现一套探测机制,可以在较短的时间内,探测到对方是否存活。

比如,web 服务软件一般都会提供 keepalive_timeout 参数,用来指定 HTTP 长连接的超时时间。如果设置了 HTTP 长连接的超时时间是 60 秒,web 服务软件就会启动一个定时器,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。

三次握手?

seq number、ack number

Time wait?

TCP丢包怎么办?

滑动窗口、流量控制?

3、HTTP/HTTP 1.1

为什么不直接使用TCP通信?

HTTP依然是TCP,只是多了这个分层能够让用户更清晰/简洁。

HTTP1.1有哪些优化?

- 长连接
- 部分传输
- HOST
- 缓存
4、HTTPS

HTTP + SSL/TLS

image.png

网络提速 - 协议优化

HTTP 2.0

多路复用/stream

image.png

如果TCP丢包怎么办?

发生队头阻塞,全部重传。

QUIC/HTTP 3.0

网络提速 - 网络路径协议优化

数据中心分布

image.png

同运营商访问

image.png

静态资源(图片视频)优化(CDN)

截屏2022-05-16 下午8.27.39.png

动态API(播放/评论接口)优化(DSA)

image.png

网络稳定 - 容灾

故障发生 -> 故障感知 -> 自动切换 -> 服务恢复

  • 案例一

image.png

通过外网容灾应对专线挂掉情况。

  • 案例二

image.png

image.png

  • 案例三

image.png

云到端 -> 主动降级/容灾

场景局限性:

- 云控本身宕机
- 用户不让执行某些命令
- web界面无法嵌入SDK
  • 案例四

image.png

Bug导致全crash -> 前置兜底逻辑/cache文件

网络稳定 - 故障

故障明确 -> 故障止损 -> 分段排查

image.png

image.png

image.png

故障排查常用命令

`dig 查询 dns 问题

`ping/telnet/nmap 查询三/四层连通性

`Traceroute 排查中间链路

`iptables

`tcpdump

  • 案例一

image.png

客户端异常 -> 服务端自测正常 -> 网关转发异常 -> 健康检查异常

  • 案例二

image.png

个别用户报故障,生产环境大多数是客户端的问题

  • 案例三

image.png

某电信报障某APP无法使用 -> 服务端正常,电信流量突降 -> 电信客户端ping不通目标服务 -> 电缆被挖断

  • 案例四

image.png

某APP故障 -> 后端服务器反馈服务正常 -> 网络转发设备异常 -> 抓包 -> 路由不对称

如何将我的服务开放给用户

企业接入

host管理 -> 域名系统

image.png

域名购买与配置迁移

image.png

域名解析绑定公网ip

自建DNS服务器

问题背景

  • 内网域名的解析也得从公网去获取,效率低下

  • 外部用户能看到内网ip地址,容易被hacker攻击

  • 云厂商权威DNS容易出故障,影响用户体验

  • 扩大品牌公司技术影响力

**从公有云托管 -> 构建自己的DNS系统 **

站在企业的角度思考,我们需要哪种DNS服务器?

权威DNS、LocalDNS(可选)

常见的开源DNS:bind、nsd、knot、coredns

image.png

接入 HTTPS 协议

问题背景

  • 页面出现某些奇怪的东西
  • 返回403
  • 页面弹窗广告

对称加密喝非对称加密

image.png

SSl握手过程(RSA)

公钥是可信的吗?会不会被劫持?

Server 端发送的是带签名的证书链

image.png

Client收到后会进行验证:

image.png

证书链

接入全站加速

源站容量问题 增加后端及其扩容;静态加速缓存

网络传输问题 动态加速DCDN

全站加速 静态加速 + 动态加速

静态加速

缓存 image.png

  • 解决服务端的“第一公里”问题 // 第一公里:要将请求尽可能的优化在靠近用户的节点上进行响应,从而缩短网络链路

  • 缓解甚至消除了不同运营商之间互联的瓶颈造成的影响

  • 减轻各省的出口带宽压力

  • 优化网上热点内容的分布

动态加速 DCDN

image.png

DCDN原理

image.png

image.png

使用全站加速

image.png

4层负载均衡

思考:怎么充分利用有限的公司ip资源?

四层负载均衡:基于IP + 端口,利用某种算法将报文转发给某个后端服务器,实现负载均衡后落地到后端服务器上。

image.png

主要功能

  • 解耦vip 和 rs

  • NAT

  • 防止攻击: syn proxy

常见的调度算法原理

image.png

常见的实现方式 FULLNAT

image.png

rs怎么知道真实的CIP?

通过TCP option字段传递,然后通过特殊的内核模块反解

4层负载均衡特点

image.png

使用4层负载均衡

image.png

7层负载均衡

四层负载对100.1.2.3 只能 bind 一个80 端口,而有多个外部站点需要使用,如何解决?

有一些7层相关的配置需求,该怎么做?

Nginx简介

image.png

Nginx内部结构

image.png

事件驱动模型

image.png

传统服务器:一个进程/线程处理一个连接/请求模型,依赖OS实现并发

Nginx:一个进程/线程处理多个连接/请求异步非阻塞模型、减少OS进程切换

image.png

Nginx 调优

image.png

使用7层负载均衡

image.png

服务开发前期,如何低成本的让别人访问自己的服务?

Ngork, Expose your localhost to the web.

使用github账号授权登陆,即可使用。详见https://dashboard.ngrok.com/get-started/setup

image.png

命令:./ngrok http 8080(将本地8080端口开放到公网)

相关实验

权威DNS及LocalDNS搭建实验

1、权威侧zone文件准备

这里拟采用著名的开源软件bind9作为DNS服务的server

新建zone文件/etc/bind/example.com.zone,并编辑为以下内容

@   IN    SOA    ns1.example.com    admin.example.com. (
        0       ; serial
        1D      ; refresh
        1H      ; retry
        1W      ; expire
        3H )    ; minimum

@    IN    NS   ns1.example.com.
; 这里ns1主机的ip地址可以换成本机地址
ns1        A    10.227.89.58
; 这里www主机的ip地址可以换成本机地址
www        A    10.227.89.58

2、#### bind9配置准备

直接编辑/etc/bind/named.conf即可,配置参考如下:

logging {
 channel default_log {
        #这里注意提前创建log目录
        file "/var/log/named/named.log" versions 10 size 200m;
        severity dynamic;
        print-category yes;
        print-severity yes;
        print-time yes;
    };
    channel query_log {
        file "/var/log/named/query.log" versions 10 size 200m;
        severity dynamic;
        print-category yes;
        print-severity yes;
        print-time yes;
    };
    channel resolver_log {
        file "/var/log/named/resolver.log" versions 10 size 200m;
        severity dynamic;
        print-category yes;
        print-severity yes;
        print-time yes;
    };
    category default {default_log;};
    category queries {query_log;};
    category query-errors {query_log;};
    category resolver {resolver_log;};
};

options {
    #这里的ip地址可以换成本机地址
    listen-on port 53 { 10.227.89.58; };
    directory "/etc/bind";
    dnssec-validation no;
    #支持递归查询
    recursion yes;
    #转发到公共DNS优先,而不是自己去迭代查询,节省网络IO资源消耗
    forward first;
    forwarders {
        223.5.5.5;
        223.6.6.6;
    };
    allow-query { any; };
};

zone "example.com" {
    type master;
    file "example.com.zone";
};

3、使用dig命令验证

  • 验证权威DNS服务命令:dig @10.227.89.58 www.example.com (10.227.89.58可以换成上面监听的本机地址),命中本地托管的zone example.com,直接吐数据

image.png

  • 验证LocalDNS服务

dig @10.227.89.58 www.toutiao.com (10.227.89.58可以换成上面监听的本机地址),未命中本地托管的zone数据,直接向任一forwarders(公共DNS)请求,获取结果后缓存到本地

image.png

git

git 配置

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:

  1. /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行 git config 时带上 --system 选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)
  2. ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 你可以传递 --global 选项让 Git 读写此文件,这会对你系统上 所有 的仓库生效。
  3. 当前使用仓库的 Git 目录中的 config 文件(即 .git/config):针对该仓库。 你可以传递 --local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。。 (当然,你需要进入某个 Git 仓库中才能让该选项生效。)

每一个级别会覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。

可以通过以下命令查看所有的配置以及它们所在的文件:

$ git config --list --show-origin

用户信息

安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

再次强调,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。

很多 GUI 工具都会在第一次运行时帮助你配置这些信息。

文本编辑器

既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 如果未配置,Git 会使用操作系统默认的文本编辑器。

如果你想使用不同的文本编辑器,例如 Emacs,可以这样做:

$ git config --global core.editor emacs

在 Windows 系统上,如果你想要使用别的文本编辑器,那么必须指定可执行文件的完整路径。 它可能随你的编辑器的打包方式而不同。

检查配置信息

如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。

$ git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...

你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig 与 ~/.gitconfig)。 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。

你可以通过输入 git config <key>: 来检查 Git 的某一项配置

$ git config user.name
John Doe