设为首页 加入收藏

TOP

[golang]使用mTLS双向加密认证http通信(一)
2023-08-26 21:10:42 】 浏览:152
Tags:golang 使用 mTLS 双向加 http 通信

前言

假设一个场景,服务端部署在内网,客户端需要通过暴露在公网的nginx与服务端进行通信。为了避免在公网进行 http 明文通信造成的信息泄露,nginx与客户端之间的通信应当使用 https 协议,并且nginx也要验证客户端的身份,也就是mTLS双向加密认证通信。

这条通信链路有三个角色:服务端、Nginx、客户端。

  • 服务端部署在内网,与nginx使用http通信。
  • 客户端在公网,与nginx使用https通信,且双向加密认证。

服务端

服务端只使用http,所以这里用gin框架写个简单的示例,返回客户端一些基本的http信息,比如客户端IP、请求方法、host等。

package main

import (
	"log"
	"net/http"
	"time"

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

/* 中间件: 获取api处理时长 */
func midElapsed(c *gin.Context) {
	start := time.Now()
	c.Next()
	elapsed := time.Since(start)
	log.Printf("API: %s, elapsed: %s", c.Request.URL.Path, elapsed)
}

/* 处理 GET / 请求 */
func f1(c *gin.Context) {
	// 获取客户端IP
	clientIP := c.ClientIP()

	// 获取请求方法
	method := c.Request.Method

	// 获取协议
	proto := c.Request.Proto

	// 获取host
	host := c.Request.Host

	// 请求Path
	path := c.Request.URL.Path

	log.Printf("客户端IP: %s, 请求方法: %s, 协议: %s, host: %s, path: %s", clientIP, method, proto, host, path)

	// 获取请求头
	headers := c.Request.Header
	for hk, hv := range headers {
		log.Printf("header key: %s, value: %s", hk, hv)
	}

	// 获取名为"mycookie"的cookie
	var cookies []string
	cookie, err := c.Cookie("mycookie")
	if err != nil {
		log.Printf("get cookie [mycookie] error: %s", err)
	} else {
		log.Printf("get cookie [mycookie]: %s", cookie)
		cookies = append(cookies, cookie)
	}

	c.JSON(http.StatusOK, gin.H{
		"clientIP": clientIP,
		"method":   method,
		"proto":    proto,
		"host":     host,
		"headers":  headers,
		"cookies":  cookies,
		"path":     path,
	})
}

func main() {
	r := gin.Default()
	r.Use(midElapsed) // 全局引用计算耗时的中间件
	r.GET("/", f1)
	r.Run("0.0.0.0:8080")
}

生成证书

  1. 生成ca根证书。生成过程会要求填写密码、CN、ON、OU等信息,记住密码,填写的信息也要和下一步openssl.cnf文件内容一致。
openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3650
  1. 新建并编辑文件openssl.cnf文件。req_distinguished_name中内容按需填写,DNS.1要替换成实际域名。
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
prompt = no

[req_distinguished_name]
countryName = CN
stateOrProvinceName = Anhui
localityName = Hefei
organizationName = zhangsan
commonName = qw.er.com

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = qw.er.com
  1. 生成服务端证书
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=qw.er.com" -config openssl.cnf

# 提示输入ca私钥的密码
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extensions v3_req -extfile openssl.cnf
  1. 生成客户端证书
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/CN=qw.er.com" -config openssl.cnf

# 提示输入ca私钥的密码
openssl x509 -req -in client.csr -out client.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extensions v3_req -extfile openssl.cnf

Nginx配置

nginx反向代理服务端的配置示例如下

server {
    listen 80 ssl;
    server_name qw.er.com;
    ssl_certificate /home/atlas/apps/nginx/certs/qwer/server.crt;
    ssl_certificate_key /home/atlas/apps/nginx/certs/qwer/server.key;
    
    # 校验客户端证书
    ssl_verify_client on;
    ssl_client_certificate /home/atlas/apps/nginx/certs/qwer/ca.crt;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇go基础-函数 下一篇Go 语法

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目