搭建nginx反向代理用做内网域名转发

作者:@ouyang 发布时间:2015年07月21日 阅读: 3,822 分类:技术相关

本文转载自:  搭建nginx反向代理用做内网域名转发 http://blog.csdn.net/tham_/article/details/45973787

在实际办公网中,因为出口IP只有一个,要实现对外提供服务的话就必须得做端口映射,如果有多个服务要对外开放的话,这只能通过映射不同端口来区分,这在实际使用过程中非常的痛苦(记忆困难、一一对应关系也没有规律、访问的时候还得加端口),这个痛苦的问题用表格的形式来形象的描述如下:

Public IP Public Port Number Internal IP Internal Port Number Note
1.1.1.1

80

192.168.1.10

80

service A
1.1.1.1

81

192.168.1.11

80

service B
1.1.1.1

8080

192.168.1.25

80

service C
1.1.1.1

443

192.168.1.26

443

service D
1.1.1.1

444

192.168.1.35

443

service E

在需要对外开放的服务很多的情况下,NAT的方式虽然难用、难记,但至少还是能够满足需求的(可用端口要小于65535个),但如果A、B、C服务都想(或者必须)使用默认的80、443端口的话,在只有一个公网IP的情况下是没法满足的,如果能有一种如下的实现方式,那就完美了:

Domain Name Public IP Public Port Number Internal IP Internal Port Number Note
A.example.com 1.1.1.1 80 192.168.1.10 80 service A
B.example.com 1.1.1.1 80 192.168.1.11 80 service B
C.example.com 1.1.1.1 80 192.168.1.25 80 service C
D.example.com 1.1.1.1 443 192.168.1.26 443 service D
E.example.com 1.1.1.1 443 192.168.1.35 443 service E

 

首先来分析一下,传统NAT的话肯定是实现不了,因为NAT是3层ip加4层端口的方式做映射,而域名(如http header中)都属于7层的内容,要实现的话只能借助支持7层http协议解析的工具实现,经过一番研究发现反向代理可以实现,那太好了,反响代理的工具一大堆:squid、apache、nginx、haproxy、mysql proxy等等,本文仅讲基于http、https协议的实现,其他协议暂不讨论。

有了工具的支持,接下来就得考虑考虑如何部署的问题:

(1)域名解析到路由器的公网ip-->在路由器(pfsense)上安装squid-->配置反向代理(开启http、https反向代理、主机映射、域名正则匹配转发)-->成功实现(需要路由器支持);

(2)域名解析到路由器的公网ip-->在路由器上做传统NAT,将80、443端口分别指向反向代理服务器-->配置反向代理服务器的-->成功实现(通用方法);

WINDOWS 2008Server 配置nginx 反向代理服务器

本案例有用过可行
0、先要在域名官网上面配置域名对应的IP地址,然后要在自己路由器上面将80端口映射到要装nginx服务器的IP地址。
1、从官网上面下载nginx1.6.2   WINDOWS版本的。访问地址http://nginx.org/en/download.html
2、解压缩到C盘根目录下面
3、复制C:\nginx\conf\nginx.conf,保存成一个副本
4、编辑nginx.conf,内容如下

 #工作进程数,建议设置为CPU的总核数

worker_processes 2;

#全局错误日志定义类型,日志等级从低到高依次为:

#debug | info | notice | warn | error | crit

error_log logs/error.log info;

#记录主进程ID的文件

pid /nginx/nginx.pid;

#一个进程能打开的文件描述符最大值,理论上该值因该是最多能打开的文件数除以进程数。

#但是由于nginx负载并不是完全均衡的,所以这个值最好等于最多能打开的文件数。

#LINUX系统可以执行 sysctl -a | grep fs.file 可以看到linux文件描述符。

worker_rlimit_nofile 65535;

#连接数上限, 单个进程允许的最大连接数

events { 

 worker_connections 65535;

}

#设定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 记录了哪些用户,哪些页面以及用户浏览器、ip和其他的访问信息

 access_log logs/access.log main;

 #服务器名字的hash表大小

 server_names_hash_bucket_size 128;

 #客户端请求头缓冲大小。

 #nginx默认会用client_header_buffer_size这个buffer来读取header值,

 #如果header过大,它会使用large_client_header_buffers来读取。

 #如果设置过小HTTP头/Cookie过大 会报400 错误 nginx 400 bad request

 #如果超过buffer,就会报HTTP 414错误(URI Too Long)

 #nginx接受最长的HTTP头部大小必须比其中一个buffer大

 #否则就会报400的HTTP错误(Bad Request)

 client_header_buffer_size 32k;

 large_client_header_buffers 4 32k;

 #客户端请求体的大小

 client_body_buffer_size 8m;

 #隐藏ngnix版本号

 server_tokens off;

 #忽略不合法的请求头

 ignore_invalid_headers on;

 #指定启用除第一条error_page指令以外其他的error_page。

 recursive_error_pages on;

 #让 nginx 在处理自己内部重定向时不默认使用 server_name 设置中的第一个域名

 server_name_in_redirect off;

 #开启文件传输,一般应用都应设置为on;若是有下载的应用,则可以设置成off来平衡网络I/O和磁盘的I/O来降低系统负载

 sendfile on;

 #告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送。

 tcp_nopush on;

 #告诉nginx不要缓存数据,而是一段一段的发送--当需要及时发送数据时,就应该给应用设置这个属性,

 #这样发送一小块数据信息时就不能立即得到返回值。

 tcp_nodelay on;

 #长连接超时时间,单位是秒

 keepalive_timeout 65;

 #gzip模块设置,使用 gzip 压缩可以降低网站带宽消耗,同时提升访问速度。

 gzip on; #开启gzip

 gzip_min_length 1k; #最小压缩大小

 gzip_buffers 4 16k; #压缩缓冲区

 gzip_http_version 1.0; #压缩版本

 gzip_comp_level 2; #压缩等级

 gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型

 #upstream作负载均衡,在此配置需要轮询的服务器地址和端口号,max_fails为允许请求失败的次数,默认为1.

 #weight为轮询权重,根据不同的权重分配可以用来平衡服务器的访问率。

 #指定要域名对应的WEB项目访问地址

 upstream hostname {

 server 192.168.33.129:18080 max_fails=0 weight=1;

 }
 #主机配置

 server {

 #监听端口

 listen 80;

 #自己指定要跳转的域名

 server_name youjie.co;

 #字符集

 charset utf-8;

 #单独的access_log文件

 access_log logs/192.168.33.129.access.log main;

 #反向代理配置,

 #将所有请求为http://hostname的请求全部转发到upstream中定义的目标服务器中。

 location / {

 #此处配置的域名必须与upstream的域名一致,才能转发。

 proxy_pass http://hostname;

 proxy_set_header X-Real-IP $remote_addr;

 }

 #启用nginx status 监听页面
 location /nginxstatus {

 stub_status on;

 access_log on;

 }

 #错误页面

 error_page 500 502 503 504 /50x.html;

 location = /50x.html {

 root html;

 }
 }

upstream hostname1 {

 server 192.168.33.129:28080 max_fails=0 weight=1;

}
 server {

 #监听端口

 listen 80;

 #自己指定要访问的域名

 server_name u-pai.cn;

 #字符集

 charset utf-8;

 #单独的access_log文件

 access_log logs/192.168.33.129.access.log main;

 #反向代理配置,

 #将所有请求为http://hostname1的请求全部转发到upstream中定义的目标服务器中。

 location / {

 #此处配置的域名必须与upstream的域名一致,才能转发。

 proxy_pass http://hostname1;

 proxy_set_header X-Real-IP $remote_addr;

 }
 #启用nginx status 监听页面

 location /nginxstatus {

 stub_status on;

 access_log on;

 }

 #错误页面

 error_page 500 502 503 504 /50x.html;

 location = /50x.html {

 root html;

 }
 }
}

到此配置完成

5、启动nginx
开始菜单-->运行-->cmd-->
cd c:\nginx\
nginx
启动完成
6、访问
现在可以在浏览器中输入u-pai,youjie.co访问到不同的网站。

搭建nginx反向代理用做内网域名转发

情景
由于内网有多台服务器的http服务要映射到公司外网静态IP,如果用路由的端口映射来做,就只能一台内网服务器的80端口映射到外网80端口,其他服务器的80端口只能映射到外网的非80端口。非80端口的映射在访问的时候要域名加上端口,比较麻烦。并且入口路由最多只能做20个端口映射。肯定以后不够用。
然后k兄就提议可以在内网搭建个nginx反向代理服务器,将nginx反向代理服务器的80映射到外网IP的80,这样指向到公司外网IP的域名的HTTP请求就会发送到nginx反向代理服务器,利用nginx反向代理将不同域名的请求转发给内网不同机器的端口,就起到了“根据域名自动转发到相应服务器的特定端口”的效果,而路由器的端口映射做到的只是“根据不同端口自动转发到相应服务器的特定端口”,真是喜大普奔啊。
涉及的知识:nginx编译安装,nginx反向代理基本配置,路由端口映射知识,还有网络域名等常识。

本次实验目标是做到:在浏览器中输入xxx123.tk能访问到内网机器192.168.10.38的3000端口,输入xxx456.tk能访问到内网机器192.168.10.40的80端口。

配置步骤
服务器ubuntu 12.04

###更新仓库
apt-get update -y
apt-get install wget -y

#下载nginx和相关软件包

pcre是为了编译rewrite模块,zlib是为了支持gzip功能。额,这里nginx版本有点旧,因为我还要做升级nginx的实验用。大家可以装新版本。

 cd /usr/local/src
 wget <a href="ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.33.tar.gz">ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.33.tar.gz</a>
 wget <a href="http://zlib.net/zlib-1.2.8.tar.gz">http://zlib.net/zlib-1.2.8.tar.gz</a>
 wget <a href="http://nginx.org/download/nginx-1.4.2.tar.gz">http://nginx.org/download/nginx-1.4.2.tar.gz</a>
 tar xf pcre-8.33.tar.gz
 tar xf zlib-1.2.8.tar.gz

#安装编译环境

apt-get install build-essential libtool -y

#创建nginx用户  ,所谓的unprivileged user

useradd -s /bin/false -r -M -d /nonexistent www

#开始编译安装

/configure --with-pcre=/usr/local/src/pcre-8.33 --with-zlib=/usr/local/src/zlib-1.2.8 --user=www --group=www \
 --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module
 make
 make install

#给文件夹授权
chown -R www:www /usr/local/nginx
#修改配置文件
vim nginx.conf

user www www;
worker_processes 1;
error_log logs/error.log;
pid logs/nginx.pid;
worker_rlimit_nofile 65535;
events {
    use epoll;
    worker_connections 65535;
}
http {
    include mime.types;
    default_type application/octet-stream;
    include /usr/local/nginx/conf/reverse-proxy.conf;
    sendfile on;
    keepalive_timeout 65;
    gzip on;
    client_max_body_size 50m;
#缓冲区代理缓冲用户端请求的最大字节数,可以理解为保存到本地再传给用户
    client_body_buffer_size 256k;
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;
    proxy_connect_timeout 300s;
#nginx跟后端服务器连接超时时间(代理连接超时)
    proxy_read_timeout 300s;
#连接成功后,后端服务器响应时间(代理接收超时)
    proxy_send_timeout 300s;
    proxy_buffer_size 64k;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
    proxy_buffers 4 32k;
#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
    proxy_busy_buffers_size 64k;
#高负荷下缓冲大小(proxy_buffers*2)
    proxy_temp_file_write_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传递请求,而不缓冲到磁盘
    proxy_ignore_client_abort on;
#不允许代理端主动关闭连接
    server {
        listen 80;
        server_name localhost;
        location / {
            root html;
            index index.html index.htm;
        }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }
    }
}

编辑反向代理服务器配置文件:
vim /usr/local/nginx/conf/reverse-proxy.conf

server
{
    listen 80;
    server_name xxx123.tk;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://192.168.10.38:3000;
    }
    access_log logs/xxx123.tk_access.log;
}
 
server
{
    listen 80;
    server_name xxx456.tk;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://192.168.10.40:80;
    }
    access_log logs/xxx456.tk_access.log;
}

然后重新加载nginx配置文件,使之修改生效,再把xxx123.tk域名指向公司静态IP,这样就成功的做到了在浏览器中输入xxx123.tk的时候访问的内网服务器192.168.10.38的3000端口,输入xxx456.tk访问192.168.10.40的80端口的作用。
如果想对后端机器做负载均衡,像下面这配置就可以把对nagios.xxx123.tk的请求分发给内网的131和132这两台机器做负载均衡了。

upstream monitor_server {
    server 192.168.0.131:80;
        server 192.168.0.132:80;
}
 
server
{
    listen 80;
    server_name nagios.xxx123.tk;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://monitor_server;
    }
    access_log logs/nagios.xxx123.tk_access.log;
}

额,关于负载均衡和缓存就不多说了,这里只是要起到一个简单的“域名转发”功能。
另外,由于http请求最后都是由反向代理服务器传递给后段的机器,所以后端的机器原来的访问日志记录的访问IP都是反向代理服务器的IP。
要想能记录真实IP,需要修改后端机器的日志格式,这里假设后端也是一台nginx:
在后端配置文件里面加入这一段即可:

log_format access '$HTTP_X_REAL_IP - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $HTTP_X_Forwarded_For';
 
access_log logs/access.log access;

再看看原来日志的格式长什么样:

#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 logs/access.log main;

看出区别了吧
遇到的问题
之前没配置下面这段,访问时候偶尔会出现504 gateway timeout,由于偶尔出现,所以不太好排查

proxy_connect_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_buffer_size 64k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_ignore_client_abort on;

报错日志:

...upstream timed out (110: Connection timed out) while reading response header from upstream, client: ...(后面的省略)

从日志看来是连接超时了,网上一通乱查之后估计可能是后端服务器响应超时了,本着大胆假设,小心求证的原则,既然假设了错误原因就要做实验重现错误:那就调整代理超时参数,反过来把代理超时阀值设小(比如1ms)看会不会次次出现504。后来发现把proxy_read_timeout 这个参数设置成1ms的时候,每次访问都出现504。于是把这个参数调大,加入上面那段配置,解决问题了。

如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!

标签: 端口, 反代理, nginx, 映射, NAT

添加新评论 »