什么,NGINX无法正向代理HTTPS?

需求

内网的机器无法访问互联网,但是有些业务服务必须要上网,这个时候就需要一个正向代理,将正向代理部署在一台可以上网的机器,业务应用通过正向代理去访问互联网,同时使用正向代理控制上网策略和权限。

什么是正向代理?

正向代理就是客户端client知道服务器server的地址,也知道proxy的地址,但是client通过proxy,并且告诉proxy,我要访问server的地址,proxy将请求直接转发到server。正向代理最常见的应用是VPN,用来突破client到server的网络限制。

与之对应的就是反向代理,反向代理是client不知道server的地址,但知道proxy的地址,client请求proxy,proxy根据配置的规则转发给server,这里client是不知道具体server的地址,都是通过proxy里的规则进行转发。反向代理最常见的工具就是Nginx。

我现在需要在linux服务器上做正向代理,查了下可以用的工具Squid,Nginx。作为研发来说,Squid比较陌生,nginx那是经常打交道,那就用nginx来搭建了。(nginx是反向代理的代表,其实也可以用来做正向代理)

nginx搭建正向代理

简单介绍下nginx做正向代理的原理,在nginx的配置中加上 resolver 8.8.8.8,其他配置通用,就可以做正向代理了,而这个配置的作用是:指定固定的DNS服务器,而8.8.8.8是Google提供的全球DNS服务器。这样就可以把请求直接转到Google的DNS服务器,然后DNS直接转发出去。完整配置如下:

ini 复制代码
worker_processes  3;
​
events {
    worker_connections  1024;
}
​
http {
    include       mime.types;
    default_type  application/octet-stream;
​
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                              '$status $body_bytes_sent $request_body "$http_referer" '
                              '"$http_user_agent" "$http_x_forwarded_for" "$request_time"';
​
    access_log  /etc/nginx/logs/access.log  main;
​
​
    sendfile        on;
​
    server {
      listen 10080; # 代理监听的端口
      proxy_connect;
      server_name *.com;
      proxy_max_temp_file_size 0; 
      resolver 8.8.8.8; # DNS 解析器,使用 Google 的公共 DNS
​
      # 处理所有 HTTP 请求
      location / {
        proxy_pass http://$http_host;
        proxy_set_header Host $http_host;
        proxy_ssl_server_name on;
        proxy_ssl_session_reuse off;
        proxy_next_upstream error timeout invalid_header http_502;
        proxy_buffer_size 4k; # 调整缓冲区大小
        proxy_buffers 4 8k;
        proxy_busy_buffers_size 16k;
        }   
     }
}

将nginx运行起来之后,可以直接用curl进行测试代理是否正常,脚本如下:

rust 复制代码
curl --proxy "http://xx.xx.xx.xx:xx" 'http://www.baidu.com'

如无意外的情况下,可以得到正常返回了。但是我把http改成https之后,立马就返回400 bad request了。这时候可能以为是配置出问题了,其实是nginx代理并不支持https的正向代理转发,搞了半天,不支持https,有点扎心,那么nginx能否支持https的正向代理呢?答案是可以的。

github上有个大神,写了个ngx_http_proxy_connect_module(github.com/chobits/ngx...),用来解决nginx代理无法转发https的问题。可以参照文档内容将模块编译到nginx中。当然如果你觉得这样比较麻烦的话,有更简单的方法。我现在运维部署一些开源软件时,基本都是用docker去部署的,使用docker部署的好处我就不在这里赘述了。那现在我就介绍一下使用docker部署nginx的方式。

首先我们就是找一个已经编译了ngx_http_proxy_connect_module的nginx打包好的镜像,我用的是这个:github.com/reiz/nginx_...。部署就简单了,docker-compose文件如下

yaml 复制代码
version: '2'
services:
  nginx:
    image: reiz/nginx_proxy:0.0.5
    container_name: proxy_nginx
    restart: always
    ports:
      - '10080:10080'
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - ./nginx.conf:/usr/local/nginx/conf/nginx.conf
      - ./logs:/etc/nginx/logs

接下来是nginx.conf:

ini 复制代码
daemon off;
worker_processes  auto;
​
events {
    worker_connections  1024;
}
​
​
http {
    server_names_hash_bucket_size 128;
​
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                              '$status $body_bytes_sent $request_body "$http_referer" '
                              '"$http_user_agent" "$http_x_forwarded_for" "$request_time"';
​
​
    access_log  /etc/nginx/logs/access.log;
    error_log   /etc/nginx/logs/error.log;
    sendfile        on;
    keepalive_timeout 65;
​
    server {
        listen       10080;
        #server_name  *.com;
​
        proxy_connect;
        resolver 8.8.8.8 ipv6=off;
        location / {
           proxy_pass http://$http_host;
           proxy_set_header Host $http_host;
        }
      }
}

nginx.conf可以配置访问的地址和禁止访问的地址,及其他的配置,可以看作者的使用文档。

问题

Cannot assign requested address

在连续请求的时候,有一半的请求会报无法分配地址,这个问题还挺棘手,最后发现是ipv6的问题,要关闭ipv6才行,resolver 8.8.8.8 ipv6=off; 关闭了之后就没有出现这个问题。

相关推荐
安的列斯凯奇11 分钟前
SpringBoot篇 单元测试 理论篇
spring boot·后端·单元测试
AI航海家(Ethan)14 分钟前
PostgreSQL数据库的运行机制和架构体系
数据库·postgresql·架构
架构文摘JGWZ40 分钟前
FastJson很快,有什么用?
后端·学习
BinaryBardC41 分钟前
Swift语言的网络编程
开发语言·后端·golang
邓熙榆1 小时前
Haskell语言的正则表达式
开发语言·后端·golang
贾贾20231 小时前
配电自动化系统“三区四层”数字化架构
运维·科技·架构·自动化·能源·制造·智能硬件
专职4 小时前
spring boot中实现手动分页
java·spring boot·后端
Ciderw4 小时前
Go中的三种锁
开发语言·c++·后端·golang·互斥锁·
m0_748246354 小时前
SpringBoot返回文件让前端下载的几种方式
前端·spring boot·后端
m0_748230445 小时前
创建一个Spring Boot项目
java·spring boot·后端