首页 > 代码库 > 基于域名的7层转发的实现(NAT+反向代理)
基于域名的7层转发的实现(NAT+反向代理)
在公司的实际办公网中,因为出口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端口分别指向反向代理服务器-->配置反向代理服务器的-->成功实现(通用方法);
其中第一个方法我已经很好的实现http的反向代理,但对于https,由于squid不支持SNI(server name Indication),仅能支持一个https站点,且很多公司用的路由器可能不支持安装squid软件,所以接下来我主要介绍通用的方法:通过在linux上安装nginx来搭建反向代理服务来支持基于域名的7层转发。
下载openssl库
wget http://www.openssl.org/source/openssl-1.0.1h.tar.gz
tar xzvf openssl-1.0.1h.tar.gz
mv openssl-1.0.1h /usr/local/openssl-1.0.1h/
下载nginx,编译时加入SNI的支持
yum install pcre pcre-devel
yum install zlib zlib-devel
wget http://nginx.org/download/nginx-1.6.0.tar.gz
tar xzvf nginx-1.6.0.tar.gz
cd nginx-1.6.0
./configure \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-openssl="/usr/local/openssl-1.0.1h/" \
--with-openssl-opt="enable-tlsext" \
--with-http_stub_status_module
make
make install
检查nginx的安装情况(关键TLS SNI support enabled):
[root@svn ~]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.6.0
built by gcc 4.1.2 20080704 (Red Hat 4.1.2-54)
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --with-http_ssl_module --with-openssl=/usr/local/openssl-1.0.1h/ --with-openssl-opt=enable-tlsext --with-http_stub_status_module
配置反向代理服务器:
[root@svn ~]# more /usr/local/nginx/conf/nginx.conf
############https server revese proxy
server {
listen 10010 ssl;
server_name app.wei.com;
#Set up your cert paths
ssl_certificate_key /usr/local/nginx/conf/ssl/app_wei.key;
ssl_certificate /usr/local/nginx/conf/ssl/app_wei.crt;
location / {
proxy_pass https://192.168.100.123;
}
}
server {
listen 10010 ssl;
server_name secure.wei.com;
#Set up your cert paths
ssl_certificate_key /usr/local/nginx/conf/ssl/mars-server.key;
ssl_certificate /usr/local/nginx/conf/ssl/mars-server.crt;
location / {
proxy_pass https://192.168.100.177:443;
}
}
############http server revese proxy
server {
listen 10086 ;
server_name secure.wei.com;
location / {
proxy_pass http://192.168.100.177;
}
}
server {
listen 10086 ;
server_name dobby.wei.com;
location / {
proxy_pass http://192.168.100.148;
}
}
路由器NAT映射:1.1.1.1:80-->反向代理的10086;1.1.1.1:443-->反向代理的10010
重启nginx就可以使用了,效果对客户端是完全透明的
? ~ curl -I https://app.wei.com
HTTP/1.1 200 OK
Server: nginx/1.6.0
Date: Sat, 26 Jul 2014 01:48:14 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.3.8
参考:
Using the Nginx Web Server as a Reverse Proxy: Multiple SSL Sites with a Single IP Address
http://www.informit.com/articles/article.aspx?p=1994795
[squid-users] Reverse proxy with multiple SSL sites
http://www.squid-cache.org/mail-archive/squid-users/201406/0102.html
SNI: 实现多域名虚拟主机的SSL/TLS认证
http://www.ttlsa.com/web/sni-multi-domain-virtual-host-ssl-tls-authentication/
http://www.ttlsa.com/web/multiple-https-host-nginx-with-a-ip-configuration/