相关链接
课前准备 (摘自学员笔记)

专有名词

  • 权威DNS:保存了相应域名的权威信息。权威DNS即通俗上“这个域名我说了算”的服务器

  • LocalDNS:缓存+递归查询,运营商(集团网)部署的本地DNS服务器,直接接受网内客户端请求

  • 根DNS服务器:全球有13台,LocalDNS未命中缓存查询的起点服务器,其公网地址具体可参考www.iana.org/domains/roo…

  • DNS Update:DNS主服务器master接受外部的变更指令

  • DNS Notify:DNS主服务器master接受变更命令后,会自增自身的serial号,同时将变更的serial号告知从服务器slave

  • DNS IXFR:DNS从服务器slave以增量的形式向master要求获取本次变更的内容

  • DNS AXFR:DNS从服务器slave以全量的形式向master要求获取当前的全量数据

  • 对称加密:使用相同的秘钥来加密传输内容,一端加密后,对端收到数据会用相同的秘钥来解密

  • 非对称加密:如果用公钥对数据进行加密,只有用对应的私钥才能解密;如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。

  • 静态加速:针对视频、图片等不变的内容,将其缓存在靠近用户的边缘节点,缓存预热后用户直接从边缘获取,从而加速访问速度;

  • 动态加速DCDN:针对API类返回值不同的请求,通过特殊的网络优化方式(路由优化、传输优化)等技术加速其达到源站的速度。

  • VIP:虚拟IP,一般作为四层反向代理的入口,client看起来一直在与VIP交互

  • RS:Real Server,VIP后实际承受client请求的服务,可能是物理机/虚拟机/容器POD

  • DPDK:Data Plane Development Kit,主要用户4层负载均衡,用于转发的网络加速领域比较多;以极大提高网卡报文的处理性能和吞吐量,提高数据平面应用程序的工作效率

  • SSL/TLS:(Secure Sockets Layer 安全套接字协议),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议

  • DPDK:Data Plane Development Kit,一种从数据面去加速网络报文处理的工具,可以极大提高数据处理性能和吞吐量,提高数据平面应用程序的工作效率

实验工具准备

基础条件:使用Linux/MacOS操作系统,windows可以安装虚拟机,Ubuntu或者Centos都行

开源软件:bind9、nginx、ngrok(ngrok.com/download)

备注:bind9和nginx使用apt-get或者yum命令安装即可


企业接入升级打怪之路

域名系统

Host 管理

example 公司在建立之初建立了一些内部站点,如办公、文档等

他们的网络运维人员靠一张 Host 表来管理从 host 到 IP 的映射

也就是说,运维编辑表,然后员工使用 FTP 协议拉取这个表

但是随着 example 公司越来越多,这一方法出现了越来越多的问题

  • 流量和负载大
  • 靠人工避免域名冲突
  • 时效性差

使用域名系统

所以 example 公司的运维打算使用域名系统替换 hosts 文件

域名购买和配置迁移

之后, example 公司去购买了域名,解决了 Host 方案的一系列问题

如何开发外部用户访问

随着公司的增长,example 公司打算开发一个外部网站,具体方案如下图

自建 DNS 服务器

问题背景

前面说到,example 公司使用域名系统替换了 Host 文件解决方案,解决了一系列问题,最终把外部网站开发给了用户,但是也出现了一些问题

所以公司的运维开始研究 DNS 系统的工作模型

DNS 查询过程

本地 DNS -> 权威 DNS

DNS 记录类型

权威 DNS 系统架构

HTTPS 协议

问题背景

随着 example 公司的不断壮大和发展,最近收到了很多用户的投诉,最后发现是由 HTTP 协议造成的

对称加密和非对称加密

SSL 的通信过程

证书链

使用 https

example 公司在使用了 https 协议之后,就不用担心明文公网传输的问题了

接入全站加速

问题背景

解决方案

  • 源站容量问题:增加后端机器扩容,使用静态加速缓存
  • 网络传输问题:动态加速 DCDN
  • 全站加速:静态加速+动态加速

静态加速 CDN

动态加速 DCDN

DCDN 原理

使用全站加速

四层负载均衡

问题背景

什么是四层负载均衡?

常见的调度算法原理

常见的实现方式 FULLNAT

在内部做一次 IP 端口的转换

四层负载均衡特点

使用四层负载均衡

七层负载均衡

问题背景

Nginx 简介

Nginx 反向代理示意图

Nginx 内部结构

事件驱动模型

异步非阻塞

Nginx 简单调优

别让 OS 限制了 Nginx 的性能

提升 CPU 使用效率

提升网络效率

使用七层负载均衡

动手实践

(以下内容鄙人全程在 WSL 中操作)

准备一个 Http 服务

我使用 gin 框架写了个 hello world,来提供 http 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "github.com/gin-gonic/gin"

func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// 配置路由

r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello World!",
})
})
// 启动 web 服务
r.Run()
}

可以看见正常运行

host 劫持实验

众所周知,hosts 文件的优先级高于 DNS 服务器,所以可以在本地将域名劫持到特定的 ip 上,以用来调试目的,下面来验证这个原理

编辑 /etc/hosts ,加入下面这一行

1
172.23.245.154  www.toutiao.com

然后就能看到效果

测试完成后记得把这一行删掉

搭建 DNS 服务器

权威侧 zone 文件准备

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

1
2
3
4
5
6
7
8
9
10
11
12
13
$TTL 10M
@ 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 172.23.245.154
; 这里www主机的ip地址可以换成本机地址
www A 172.23.245.154

bind9 配置准备

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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 8053 { 127.0.0.1; }; // 鄙人按:这个服务的端口要记着
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" { // 权威 DNS
type master;
file "example.com.zone"; // 匹配上这个域名就去找上面编辑的 example.com.zone 文件
};

前车之鉴:一定要把默认有的三行 include 给注释掉

运行 bind6

用下面这个命令

1
sudo named -g

如果有报错的话,自己排查一下

使用 dig 命令验证

  • 验证权威 DNS 服务

    1
    dig @127.0.0.1 -p 8053 www.example.com # 从本机的 8053 端口找域名

  • 验证 LocalDNS 服务

    1
    dig @127.0.0.1 -p 8053 www.toutiao.com

    未命中本地托管的 zone 数据,直接向任一 forwarders(公共DNS)请求,获取结果后缓存到本地

四层负载均衡实验

正经的四层负载均衡要使用 LVS+keepalived ,但是配置专业的东西过于麻烦,这里就使用 nginx 来演示一下

四层的负载均衡就是一个网关的机子转发流量到内部的机子里,但是我们现在只有一台机子,也就只能将就着玩一下

目前我们一个有了两个服务:

  • 8053 端口的 DNS 服务
  • 8080 端口的 http 服务

现在我们把 53 端口的 udp 报文转发到 8053 去,80 端口的 tcp 报文转发到 8080 去

编辑 /etc/nginx/nginx.conf ,新增stream模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#四层转发,tcp/udp协议转发
stream {
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

access_log /var/log/nginx/access.log proxy;
open_log_file_cache off;

upstream dns_proxy {
server 127.0.0.1:8053; # 发送到本地的 8053
}
upstream hello_proxy {
server 127.0.0.1:8080; # 发到本地的 1080
}
server {
listen 53 udp reuseport; # 监听 53 端口
proxy_pass dns_proxy; # 发送到 dns_proxy
}
server {
listen 81; # 监听 81 端口
proxy_connect_timeout 1s;
proxy_timeout 300s;
proxy_pass hello_proxy; # 发到 hello_proxy
}
}

流量转发验证

  • UDP 流量

    看,请求 53 端口照样可以找到 DNS 服务

  • TCP 流量

    可以看见 81 端口也正常地转发了

七层负载均衡实验

也是转发,但是是在第七层

继续编辑 nginx 的配置文件,把 880 端口的 http 请求转发到 8080 去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
http {
include mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
upstream backend {
server 127.0.0.1:8080;
}
server {
listen 880;
server_name www.example.com;
location / {
proxy_pass http://backend;
proxy_set_header HOST $host;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
}
}
}

使用下面的命令重载 nginx 的配置文件

1
sudo nginx -s reload

然后检查,可以看见能够成功转发

而且是真的在第 7 层转发的,有日志记录

SSL 自签证书实验

(略,感觉平时会怎么配 SSL 证书就够了)

但是这个是在七层负载的同时上 SSL 证书,感兴趣的也可以去试一下

将本地服务开放外网访问

(略,感觉会 frp,nps之类的也够了)