当前位置:网站首页>Introduction to the Internet (2)

Introduction to the Internet (2)

2022-08-10 14:54:00 androidGreenHand

网络初识(一)

CA证书

CA证书:The client identifies the identity certificate for accessing the server.换句话说,客户端访问www.58.com,How can I be sure that the returned message is58服务器返回的数据,instead of the message returned by the fake website.Authorities issue digital certificates to servers.

CA机构:(Certificate Authority)即颁发数字证书的机构.是电子交易、网络数据交流中权威的受信任的第三方机构,承担公钥体系中公钥的合法性检验的责任.(机构私钥A 机构公钥A)The institutional public key is built into the computer's operating system.

服务器申请证书

  1. 服务器向证书机构申请证书,同时提供自己的域名、地址、公钥等信息.
  2. The certificate authority uses its own private key to asymmetrically encrypt the server information to obtain the certificate
  • 证书机构对服务器的信息使用hashThe algorithm produces a summary,并对这份摘要使用自己的私钥进行非对称加密得到证书数字签名.
  • 证书机构把服务器信息(明文)+数字签名+证书机构信息发送给服务器.
  1. 客户端请求服务器时,服务器把证书返回给客户端.

客户端验证证书

  1. 客户端拿到证书,得到服务器信息、数字签名、证书机构信息.
  2. 客户端对服务器信息进行hash算法计算得出一份摘要S1.
  3. 客户端使用证书机构的公钥对数字签名进行解密得到一份摘要S2.
  4. 对比S1和S2即可辨别此证书是否来自服务器且没经过篡改.

证书链

计算机产商,会在系统中安装一些根证书机构的信息,其中就包含了这些机构的公钥.这些公钥是在一定程度上是绝对安全的,是可以信任的.客户端可以使用这些公钥对数字签名进行解密.系统中预装的证书机构是有限的,但世界上每时每刻申请数字证书却非常多,他们“忙不过来”,因此有了二级证书机构.二级证书机构由根证书机构签发,二级证书机构再去给服务器签发证书.

  1. 利用根证书机构给二级证书机构签发的时候同样是一份数字证书,其中包含了二级证书机构信息、数字签名、根证书机构信息.
  2. 服务器的数字证书中包含了二级证书机构的数字证书.
  3. 客户端使用根证书机构的公钥对二级证书机构的数字签名进行解密得到摘要再进行比对,得到二级证书机构的公钥.
  4. 使用二级证书机构的公钥对服务器证书进行验证.

58同城证书

58网页证书链
58网页证书链

58网页就是包含了三级的证书机构的证书链
根证书颁发机构——过期时间:2029年3月18日 星期日 中国标准时间 18:00:00 中级证书颁发机构——过期时间:2028年11月21日 星期二 中国标准时间 08:00:00 *.58.com 过期时间:2022年3月24日 星期四 中国标准时间 15:26:02c

58网页证书
58网页证书
openssl制作CA根证书
  1. 生成java支持的私钥
openssl genrsa -des3 -out ca.key 2048 
openssl pkcs8 -topk8 -nocrypt -inform PEM -outform DER -in ca.key -out ca_private.pem
  1. 再通过CA私钥生成CA证书
openssl req -sha256 -new -x509 -days 365 -key ca.key -out ca.crt \
    -subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=ProxyeeRoot"

具体可以看这篇文章openssl用法详解

ca证书
ca证书

Https通信过程

对称加密

对称加密是指加密和解密都用同一份密钥

非对称加密

非对称加密对应于一对密钥,称为私钥和公钥,用私钥加密后需要用公钥解密,用公钥加密后需要用私钥解密

建立连接的过程

  1. 客户端向服务端发起请求,客户端生成随机数R1(ClientRandom) 发送给服务端;告诉服务端自己支持哪些加密算法

Client Hello报文: as a start of negotiation. The message mainly contains:TLS版本号,随机数(Client Random),密码套件列表,以及sessionID. 其中

  • TLS版本号:用来确定当前TLS采用的版本,目前有TLS1.0,TLS1.1, TLS1.2,TLS1.3.

  • ClientRandom:客户端生成的随机数R1,用于密钥的制作.

  • 密码套件列表:Send all cipher suites supported by the client to the server,The server picks one of the cipher suites and returns it to the client.

  • SessionID:用来表示客户端是否想复用先前存在的session.如果不复用,则此字段为0;如果想要复用,则此字段为想要复用的sessionID.是否复用由服务端确定.

  1. 服务器向客户端发送数字证书,服务端生成随机数R2(Server Random),从客户端支持的加密算法中选择一种双方都支持的加密算法(此算法用于后面的会话密钥生成),服务端把证书、随机数R2、加密算法,一同发给客户端;

Server Hello, Certificate, ServerHelloDone共计三个报文

  • ServerHello 报文: 是对ClientHelloThe result of negotiation and confirmation in the message.包括:TLS版本号,随机数(Server Random), SerssionID, 加密套件.

  • Certificate 报文:返回数字证书

  • ServerHelloDone 报文:表明服务端的响应已经发送完毕,The client can perform subsequent processing operations;

  1. 客户端验证数字证书.
  • 验证证书的可靠性,先用CA的公钥解密被加密过后的证书,能解密则说明证书没有问题,然后通过证书里提供的摘要算法进行对数据进行摘要,然后通过自己生成的摘要与服务端发送的摘要比对.

  • 验证证书合法性,包括证书是否吊销、是否到期、域名是否匹配,通过后则进行后面的流程

  • 获得公钥、会话密钥生成算法、随机数R2

    • Get the server's public key from the server certificate、
    • from the data returned by the server 会话密钥生成算法、随机数R2
  • 生成一个随机数R3,根据会话秘钥算法使用R1、R2、R3生成会话秘钥

  • 用服务端证书的公钥加密随机数R3并发送给服务端.

ClientKeyExchange 报文:Carry all the information that the client exchanged for the key Change Cipher Spec 报文:Notify the server to use the new encryption method for the next transmitted data. Encrypted handshake 报文:The first message encrypted with a symmetric key,如果这个报文加解密校验成功,那么就说明对称秘钥是正确的.

PreMasterKey:is the third random numberR3

  1. 服务器得到会话密钥

(1)服务器用私钥解密客户端发过来的随机数R3

(2)根据会话秘钥算法使用R1、R2、R3生成会话秘钥

Https通信过程
Https通信过程

通信的过程

  1. 客户端使用会话密钥对传输的数据进行对称加密传输给服务器;
  2. 服务器使用会话密钥对传输的数据进行解密;
  3. 服务器使用会话密钥对响应的数据进行对称加密传输给客户端;
  4. 客户端使用会话密钥对传输的数据进行解密;

charles 抓包原理

  1. 客户端向服务器发起HTTPS请求,charles截获客户端发送给服务器的HTTPS请求,charles伪装成客户端向服务器发送请求进行握手.

  2. 服务器发回响应,charles获取到服务器的CA证书,用根证书(内置)公钥进行解密,验证服务器数据签名,获取到服务器CA证书公钥.然后charles伪造自己的CA证书(这里的CA证书,也是根证书,只不过是charles伪造的根证书),Impersonate the server certificate to pass to the client.

  3. 与普通过程中客户端的操作相同,客户端根据返回的数据进行证书校验、生成R3、用charles伪造的证书公钥加密,并生成HTTPS通信用的对称密钥.

  4. The client will have important information(CharlesThe random number encrypted by the public key)传递给服务器,又被charles截获.charles将截获的密文用自己伪造证书的私钥解开,获得并计算得到HTTPS通信用的对称密钥.charlesThe data sent by the client is encrypted with the public key of the server certificate and transmitted to the server.

  5. 与普通过程中服务器端的操作相同,服务器用私钥解开后建立信任,Then send the encrypted message to the client.

  6. charles截获服务器发送的密文,用对称密钥解开,再用自己伪造证书的私钥加密传给客户端.

  7. 客户端拿到加密信息后,用公钥解开,验证HASH.The establishment of the connection is officially completed,客户端与服务器端就这样建立了”信任“.

charles抓包过程
charles抓包过程
During normal encrypted communication:
  1. 服务器—>客户端:charles接收到服务器发送的密文,用对称密钥解开,获得服务器发送的明文.Again encrypted and sent to the client.
  2. 客户端—>服务端:客户端用对称密钥加密,被charles截获后,解密获得明文.再次加密,发送给服务器端.由于charles一直拥有通信用对称密钥,所以在整个HTTPS通信过程中信息对其透明.

Netty

netty介绍

Netty Netty 是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序.它极大地简化和流线了网络编程.

Netty核心组件

Handler

为了支持各种协议和处理数据的方式,便诞生了Handler组件.Handler主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等.The business handled by yourself needs to be inheritedHandler.

ChannelInitializer

当一个链接建立时,Need to know how to receive or send data,Of course we have all kindsHandler实现来处理它,那么ChannelInitializer便是用来配置这些Handler,它会提供一个ChannelPipeline,并把Handler加入到ChannelPipeline.

Pipeline(ChannelPipeline)

ChannelPipeline 是一个 Handler 的集合,它负责处理和拦截 Channel 的入站事件和出站操作,相当于一个贯穿 Netty 的链.ChannelPipeline 实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 Channel 中各个的 ChannelHandler 如何相互交互.ChannelPipeline负责安排Handler的顺序及其执行

Channels

NIO的基本组件,表示一个打开的连接(网络,文件),可以用于处理一个或者多个不同的I/O操作(读/写)

netty写一个简单的demo

HTTP代理

HTTP:超文本传输协议 HTTP协议传输数据是明文传输,任意的人抓包就能看到传输的数据,试着用netty抓一下HTTP请求,http请求经过代理服务器,代理服务器只要负责转发相应的http响应体就可以了.

public class CustomHttpServer {

    private final int port;

    public CustomHttpServer(int port) {
        this.port = port;
    }

    public static void main(String[] args) throws Exception {
        new CustomHttpServer(8887).start();
    }

    public void start() throws Exception {
        ServerBootstrap b = new ServerBootstrap(); // 引导器,used to configure parameters
        NioEventLoopGroup group = new NioEventLoopGroup(); //创建一个线程组:Used to handle network events(接受客户端连接
        b.group(group)
                .channel(NioServerSocketChannel.class) //使用 NioServerSocketChannel Implemented as a server-side channel
                .childHandler(new ChannelInitializer<SocketChannel>() 
// 创建一个通道初始化对象
                    @Override
                    public void initChannel(SocketChannel ch) //往 Pipeline Add custom business to the chain
                    throws Exception 
{
                        System.out.println("initChannel ch:" + ch);
                        ch.pipeline()
                                .addLast("decoder"new HttpRequestDecoder())   // 用于解码request
                                .addLast("encoder"new HttpResponseEncoder())  // 用于编码response
                                .addLast("aggregator"new HttpObjectAggregator(512 * 1024))  // 消息聚合器
                                .addLast("handler"new HttpHandler());        // 自定义的业务处理
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128// determining the number of connections queued
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);

        b.bind(port).sync();
    }

    public static class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest// 1

        private AsciiString contentType = HttpHeaderValues.TEXT_PLAIN;

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {


            System.out.println("gzp_uri:" + msg.getUri());
            if(msg.getUri().startsWith("www.baidu.com")){
                System.out.println("gzp_uri_www.baidu.com:" + msg.getUri());
            }
            if(msg.getUri().startsWith("http://")){
                System.out.println("gzp_uri_http://" + msg.getUri());
                ByteBuf buf= msg.content();
                byte[] bytes= new byte[buf.readableBytes()];//
                buf.getBytes(buf.readerIndex(),bytes);
                String str =new String(bytes);
                System.out.println("gzp_uri_http_content://" + str);
            }
            DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                    new HttpResponseStatus(200,
                            "Connection established"),
                    Unpooled.wrappedBuffer("<script> alert('this is insert alert   hello android ')</script>".getBytes())); // 2


            HttpHeaders heads = response.headers();
            heads.add(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=UTF-8");
            heads.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); // 3
            heads.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);

            ctx.write(response); //将数据写到ChannelPipeline中的下一个 ChannelHandler 开始处理
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            System.out.println("channelReadComplete");
            super.channelReadComplete(ctx);
            ctx.flush(); // 4
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            System.out.println("exceptionCaught");
            if (null != cause) cause.printStackTrace();
            if (null != ctx) ctx.close();
        }
    }
}

HTTPS代理

https请求经过代理服务器,会发送一个CONNECT报文,用于和代理服务器建立隧道,如果代理服务器返回HTTP 200,则建立成功,后续代理服务器只要负责转发数据就行,实际上SSL/TLS握手还是发生在客户端和真实服务器.

思路

创建SocketServer监听端口,根据http请求头方法如果是CONNECT就是HTTPS请求否则都为HTTP请求,接着根据HOST头建立代理服务器与目标服务器的连接,然后转发数据.HTTPS请求需要特殊处理,因为CONNECT请求并不需要转发,要返回一个HTTP 200的响应建立隧道,之后才进行转发.

原网站

版权声明
本文为[androidGreenHand]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208101431162883.html