第九节:将我的服务开放给用户丨青训营笔记

169 阅读6分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第8篇笔记。

1. 专有名词

  • 权威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,一种从数据面去加速网络报文处理的工具,可以极大提高数据处理性能和吞吐量,提高数据平面应用程序的工作效率

2. 实验工具准备

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

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

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

3. 实操环节

3.1 后端准备

准备一个网站,这里html等内容的建设步骤不在本次分享范围内,我们就以最简单的helloworld为例;

http访问监听的IP端口就返回‘Hello, World!’

3.2 host劫持实验

一般来说,操作系统会优先查看本地/etc/hosts目录去匹配相应的IP,而不是再去查询DNS系统,使用此类方式可以在本地将域名劫持到特定的ip上,以用来调试目的

在/etc/hosts文件追加一行:'{$劫持的ip} www.toutiao.com' 此处以 www.toutiao.com 举例

3.3 权威DNS及LocalDNS搭建实验

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

3.3.1 权威侧zone文件准备

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

$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    10.227.89.58
; 这里www主机的ip地址可以换成本机地址
www        A    10.227.89.58
复制代码

3.3.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.3.3 使用dig命令验证

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

DNS请求日志见query.log

  • 验证LocalDNS服务

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

DNS 请求日志见 query.log

3.4 四层负载均衡实验

这里没有选择使用专业的LVS+keepalived作为4层转发的样例,这一层对于个人站点搭建来说是可有可无的,学员们需要有这一层概念即可,此次实验选择nginx的stream模块作为4层负载均衡实验的基础软件。

实验目的

  1. 将到达本机的53端口的udp报文转发到DNS服务器
  1. 将到达本机的80端口的tcp报文转发到自己准备的hello_world后端服务上。

3.4.1 修改DNS服务监听的端口

因为我们都是在同一台Linux机器上进行实验,不能监听相同的端口,故这里我们修改下DNS服务监听的端口,这里我们将53端口改成其他端口,从而腾出53端口给VIP(这里VIP等于本机IP)使用。

options {
    #这里的ip地址可以换成本机地址
    listen-on port 8053 { 10.227.89.58; };
    directory "/etc/bind";
    ......
};
复制代码

3.4.2 nginx stream配置准备

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

ps:若nginx未安装stream模块,则自行添加stream模块或者重新编译nginx即可。

#四层转发,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 10.227.89.58:8053;
    }
    upstream hello_proxy {
        server 10.227.89.58:8080;
    }
    server {
        listen 53 udp reuseport;
        proxy_pass dns_proxy;
    }
    server {
        listen 80;
        proxy_connect_timeout 1s;
        proxy_timeout 300s;
        proxy_pass hello_proxy;
    }
}
复制代码

3.4.3 流量转发验证

  1. UDP流量

此处dig的验证效果和4.3.3表面上看似无异,但是4层流量是经过nginx stream模块转发的,这里我们可以查询转发日志查询UDP流量转发详情。

  1. TCP流量

访问效果和直接访问后端无异

转发日志如下:

3.5 七层负载均衡实验

这里需要使用nginx的http module在四层负载均衡和后端服务之间添加七层负载均衡服务,这里以880端口为例,修改如下:
将四层负载均衡的后端设置为7层监控的端口880

upstream hello_proxy {
        server 10.227.89.58:880;
    }
复制代码

http模块配置如下:

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 10.227.89.58: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;
        }
    }
}
复制代码

访问本地服务80端口现象与上相同,nginx四七层转发日志如下:

3.6 SSL自签证书实验

下面我们来支持使用https协议访问我们的后端,SSL卸载的任务一般落在七层负载均衡这一层。

下载自签证书生成工具

3.6.1 使用工具签发自定义证书链

  • 签发根证书
    命令:./certmaker -gen root -cn "Test Root Ca"
    结果:生成文件为根证书私钥rootCA.key和证书文件rootCA.pem
  • 签发中间CA证书
    命令:./certmaker -gen intermediate -cn "TestIntermediateCA" -issuer rootCA.pem -issuerkey rootCA.key
    结果:生成中间CA证书私钥TestIntermediateCA.key和证书文件TestIntermediateCA.pem
  • 签发域名证书
    命令:./certmaker -gen cert -cn "*.example.com" -issuer TestIntermediateCA.pem -issuerkey TestIntermediateCA.key
    结果:生成域名证书私钥_.example.com.key和证书文件_.example.com.pem

3.6.2 nginx配置准备

  • 增加443端口转发四层配置
upstream hello_proxy_ssl {
    server 10.227.89.58:8443;
}
server {
    listen 443;
    proxy_connect_timeout 1s;
    proxy_timeout 300s;
    proxy_pass hello_proxy_ssl;
}
复制代码
  • server块增加ssl配置
server {
    listen  880;
    listen  8443 ssl;
    server_name  www.example.com;
    # 引用中间CA证书
    ssl_certificate      /etc/nginx/ssl/TestIntermediateCA.pem;
    ssl_certificate_key  /etc/nginx/ssl/TestIntermediateCA.key;
    # 引用域名证书
    ssl_certificate      /etc/nginx/ssl/_.example.com.pem;
    ssl_certificate_key  /etc/nginx/ssl/_.example.com.key;
    # 自动跳转到HTTPS
    if ($server_port = 880) {
        rewrite ^(.*)$ https://$host$1 permanent;
    }
    ...
}
复制代码

3.6.3 访问https

  • 443端口四七层转发日志:

  • 浏览器使用https协议访问:

3.7 将本地服务开放外网访问

有的同学可能觉得部署这一套可能太复杂,在项目前期有没有什么比较简单有效的方法将我本机的服务开放在公网供别人访问。这里简单介绍一种成熟的的解决方案。

项目地址:ngrok.com/

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

服务状态:

访问工具提供的域名:

GitHub仓库 (必须)

github.com/chanyean/yo…

参考文档

域名系统 zh.wikipedia.org/wiki/%E5%9F…

DNS解析过程 www.cnblogs.com/ximu-xin/p/…

HTTPS原理 segmentfault.com/a/119000002…

CDN静态加速原理 www.jianshu.com/p/1dae6e168…

全站加速 help.aliyun.com/document_de…

LVS+KeepAlived wsgzao.github.io/post/lvs-ke…

nginx官网 nginx.org/

nginx指令集 nginx.org/en/docs/dir…