ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 端口转发方法

端口转发方法

Linux操作系统 作者:shilei1 时间:2017-03-29 00:32:23 0 删除 编辑

0x00 故事是这样开始的

话说某一日,突然发现自己闲来无事就喜欢F5(Command+R)的MUD游戏网站(论坛)突然无法访问了!下意识地ping之:

C:\Users\xxx>ping pkuxkx.net

正在 Ping pkuxkx.net [211.154.198.9] 具有 32 字节的数据:
来自 211.154.198.9 的回复: 字节=32 时间=15ms TTL=128
来自 211.154.198.9 的回复: 字节=32 时间=8ms TTL=128
来自 211.154.198.9 的回复: 字节=32 时间=9ms TTL=128
来自 211.154.198.9 的回复: 字节=32 时间=6ms TTL=128

211.154.198.9 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 6ms,最长 = 15ms,平均 = 9ms

发现到服务器IP的网络是通的。那是服务down掉了?火速登陆QQ群,质问Admin故障原因,获知原来是由于机房问题,网站的80端口暂时无法访问。我……感谢机房,帮助我等沉迷人士戒除网瘾。

可是不过半天功夫就出现了戒断反应,开始坐立不安……怎么办?于是开始琢磨解决方案。

0x01 只科普一个概念:端口

这里先给非计算机专业的同学科普一下端口的含义,之后的概念就科普不能了,pkuxkx.net的朋友直接跳过鬼画符段落,看能看懂的操作就好:)

这里提到的端口,是网络通信上的一个概念。网络上两个主机A、B之间的任何一次通信,实际上是从A的某个端口和B的某个端口之间的通信。假设A上的进程A1和B上的进程B1通信,同时A上的进程A2和B上的进程B2通信,那么A1到B1的数据到达B后,B怎么知道该把这些数据发给B1,而不是发给B2从而引起混乱呢?这是我们就需要给A1←->B1和A2←->B2这两条通信路径分别绑定不同的端口,让它们两对各行其道、互不干扰。比如,A1绑定A的PA1端口,A2绑定A的PA2端口,B1绑定B的PB1端口,B2绑定B的PB2端口,这样A1就可以明确地告诉通信设备,它要把数据发往B的PB1端口,这样B收到数据后就知道这些数据应该给B1进程而不是其他进程了!从B到A的数据发送同理。端口是用端口号来标记的(0~65535),每个端口号对应一个端口。每个端口最多只能绑定一个进程。

端口的通信如下:

我们平时玩MUD,连接服务器时,都需要指定端口,比如:pkuxkx.net 5555,告诉我们的MUD客户端——ZMUD、MUSHClient等等去访问pkuxkx服务器的这个端口,才能够找到服务器上的对应MUD服务进程。而访问网站,比如当输入网址访问北侠论坛时 http://pkuxkx.net/forum 时,为什么没有带端口号呢?这是因为,访问web页面时,浏览器会自动为我们访问的目标ip加上web默认的端口:80。换言之,你在浏览器里输入 http://pkuxkx.net/forum 和 http://pkuxkx.net:80/forum 的效果是完全一样的。注意端口号的位置,是紧跟在指向IP的域名之后,而不是整个网址的末尾。

0x02 北侠网站端口故障初步解决方案

所以这回差不多该明白了,北侠网站的端口故障其实是这样的:

其实服务器上的进程状态杠杠滴,只是80端口对外的这条“线”被机房“剪断”了,泪目……还好北侠管理员第一时间在服务器上开放了9999端口,通过访问9999端口,玩家可以获得和访问之前的80端口相同的信息。比如之前访问论坛的网址是 http://pkuxkx.net/forum ,现在通过 http://pkuxkx.net:9999/forum 可以访问。另外MUD游戏里的fullme图片给出的验证码图片网址,也同样可以通过在“pkuxkx.net”后面加9999端口的方法来解决。比如当你在MUD里fullme(fullme验证码是北大侠客行MUD用来遏制全自动机器人,维护手动玩家乐趣的一种防挂机手段——小编注),出现以下提示——

白马客栈 -
   这是洛阳城里最大的一家客栈,紧靠洛阳中心,以洛阳的名胜白马寺来命名,曰「白马客栈」,由于价格公道,因此到这里来借宿的客人川流不息,络绎不绝,生意极其兴隆,大堂内摆了七八张桌子,店小二跑来跑去接待着从四面八方来的客人。客栈后面是客人休息的地方。柜台前摆着一个牌子(sign)。
   你可以看看(look):sign
   这里明显的出口是 east 和 west。
   店小二(Xiao er)
> 店小二用脖子上的毛巾抹了抹手,说道:这位女侠,请进请进。
fullme
你现在才来呀,不过总比不来好。
你的客户端不支持MXP,请直接打开链接查看图片。
请注意,忽略验证码中的红色文字。
http://pkuxkx.net/antirobot/robot.php?filename=xxxxxx
请输入你看到的图片上的内容。如果感觉难以识别,可以刷新一下再看看。
还是用这个命令,指令格式: fullme 验证码

这时我们直接用上面的网址已经访问不到相关的图片了(显然这个网址走的也是80端口),而可以改用以下方式访问:http://pkuxkx.net:9999/antirobot/robot.php?filename=xxxxxx ——注意端口号的添加位置。

OK,虽然看上去很麻烦,但是我们的紧急需求算是初步解决了。这种方案的实现原理是什么呢?其实就是在服务器后台做了一个简单的端口转发,从内部将访问pkuxkx.net:9999的数据导到pkuxkx.net:80,然后再把pkuxkx.net:80发出的数据导回pkuxkx.net:9999,最终返回到玩家那里。一图以蔽之:

注意上图中绿色的线,代表数据畅通无阻的路线。其中北侠服务器的80端口是可以从本机访问的(就是端口z的位置),只是不能由远程服务器从外部(端口x的位置)访问。端口号x、y、z是系统在连接时自动分配的端口号,这里我们不用care它们的具体数字。

是的,由于本文的目的之一是学习和总结提高,所以要八一八更具体的方法,对此不感兴趣、想看解决方案汇总的不用犹豫,用力地划动手机屏幕到页面底部吧……

接下来,关于端口转发的iptables、SSH、Nginx等方法,我们一个一个八过去。

以下解决方案的前提是,北大侠客行MUD服务器端的web端口已经开在了9999。但是这样对玩家来说仍有很多不便,例如:

  1. 需要改fullme插件,在每个域名(也就是“pkuxkx.net”)后加9999,多有不便,甚至有些玩家还不会改fullme插件的触发器=.=

  2. 北侠Wiki的访问,虽然用 http://pkuxkx.net:9999/wiki 理论上可行,但是需要加载一些样式、图片之类的资源,这些内容的请求地址是写死的,仍然会去请求 pkuxkx.net,所以改端口对这类访问无用。会导致wiki的访问极慢(所有请求超时后浏览器上才会显示相关页面内容,所以那些说9999端口访问不了wiki的,你们只要不嫌弃格式丑,多等等就出来啦)、格式也发生缺失,如下图:

作为一个有强迫症的小编,对此感到非常不适(根据NASA公布的最新13星座对应表,天蝎座的我已变身处女座T_T),所以以下解决方案都是以现存问题为解决目标各种展开。有兴趣的看官咱们继续。

0x03 iptables转发规则

如果咱们自己的日常PC的操作系统是Linux,那就再好不过了,可以直接修改iptables,让所有访问pkuxkx.net:80的流量都转发到pkuxkx.net:9999,这样所有web访问(论坛、wik、fullme,我会说还有SVN吗=.=)就不需要额外加端口了;但是考虑到大多数玩家都用的Windows系统(或者一小撮Mac用户?OS X也是没有iptables的,不过有类似的工具替代),所以更大众的解决方案可能是,由部分玩家提供一个能访问80端口的远程Linux服务器作为转发服务器,这个服务器上的80端口接受玩家访问(比如访问论坛时,玩家需要在浏览器里输入类似 http://xx.xx.xx.xx/forum ,其中xx.xx.xx.xx是转发服务器IP),然后将访问流量转发到pkuxkx.net:9999上去,实现玩家与北侠服务器之间的桥梁,如下图所示。本节之后的内容就是以配置这样的转发服务器为目标(什么?你没有转发服务器?请加入北大侠客行MUD官方QQ群询问已经配好的IP地址,QQ群号是152814678)。

iptables工作在用户空间中,是定义规则的工具。它通过将规则组成一个列表,实现绝对详细的访问控制功能。它定义的规则,可以让内核空间中的netfilter来读取,并实现让防火墙工作。netfilter作用在TCP/IP协议栈经过的地方。

关于iptables和netfilter所扮演的角色,网络上copy下来一张图(对此图一知半解,先抄下来=.=):

netfilter在内核空间中作用的位置有5个,如下图:

这五个位置也被称为五个钩子函数(hook functions)或规则链。

  1. PREROUTING (路由前)

  2. INPUT (数据包流入口)

  3. FORWARD (转发管卡)

  4. OUTPUT(数据包出口)

  5. POSTROUTING(路由后)

iptables的定义规则方式:

iptables [-t table] COMMAND chain CRETIRIA -j ACTION

规则说明:

  • -t table: filter/nat(地址转换)/mangle(修改报文原数据)

  • COMMAND:定义如何对规则进行管理

  • chain:指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的

  • CRETIRIA:指定匹配标准

  • -j ACTION:指定如何进行处理

越说越多了=.= 关于iptables的介绍暂时到此为止,各参数的说明就不展开了,详细可以参考手册。还是来看看转发服务器应该如何配置,直接上指令:

echo 1 > /proc/sys/net/ipv4/ip_forward # 指令3.0:打开IP转发
iptables -t nat -A PREROUTING -p tcp -d 10.1.9.131 --dport 80 -j DNAT --to 211.154.198.9:9999 # 指令3.1

  • -A:追加,在当前链的最后新增一个规则。

  • PREROUTING:因为是远程(远程指的是玩家数据来自远程主机而非本地主机)端口转发,那么数据包会经过网卡。这种数据包在iptables经过PREROUTING链,所以需要在PREROUTING链中加入规则。

  • -p:匹配协议。协议一般指TCP/UDP/ICMP。

  • -d:匹配目标地址。

  • —dport:指定目标端口。

  • -j DNAT —to IP[-IP][:端口[-端口]]:修改目标地址。

关于DNAT(Destination Network Address Translation,目标地址转换),修改的是IP数据报的目标地址。执行上面这条命令之后,来自玩家的数据报是可以被转发到pkuxkx.net:9999(上面的211.154.198.9就是北侠服务器目前的真实IP)了,但是站在北侠服务器的角度,由于IP数据报的源地址没有被改变,所以它返回的数据还会奔着玩家IP去——然而玩家主机和北侠服务器并没有建立TCP连接,所以从北侠服务器发往玩家主机的IP数据报就要丢失了,这里我们也需要修改IP数据报的源地址,把发往211.154.198.9的IP数据报的源地址改为本服务器的地址(一般是eth0绑定的地址,这里是10.1.9.131),这样数据就可以有来有往了:

iptables -t nat -A POSTROUTING -d 211.154.198.9 -j SNAT --to-source 10.1.9.131 # 指令3.2

指令1.2还可以用以下的指令1.3来代替,适用于当前(转发)服务器IP不固定的时候。

iptables -t nat -A POSTROUTING -j MASQUERADE # 指令3.3

另外,调试时经常需要清空规则,方法是:

iptables -F -t nat # 指令3.4

OK,iptables端口转发至此完成。可以把这个转发服务器发给朋友,让他们用http://xx.xx.xx.xx 来访问北侠网站了!不过每次都输入IP地址,麻烦又难记,怎么在输入地址时像从前一样只输入 http://pkuxkx.net 呢?这个就要涉及DNS(Domain Name System,域名系统)解析了。

0x04 DNS解析配置

DNS解析的概念比较简单。当我们输入一个域名,比如 pkuxkx.net 时,系统如何知道这个域名指向的目标IP是211.154.198.9还是xx.xx.xx.xx呢?这就是DNS解析提供的服务内容。

正常情况下,DNS解析是自动完成的,不需要用户操心。不过我们可以自己通过手动配置文件来人工干预系统的DNS解析。

本节我们的任务目标是,承接上节,通过修改本机的DNS解析配置,使得当自己访问 http://pkuxkx.net 时,系统自动访问 http://xx.xx.xx.xx ,从而实现对北侠网站的访问。

  • Windows 用户,用管理员权限打开记事本,然后找到 C:\Windows\System32\drivers\etc\hosts,在最后添加 xx.xx.xx.xx pkuxkx.net,然后重启浏览器。不同Windows版本的hosts文件位置可能不同,详情可以百度“修改hosts文件”,或者加北侠QQ群,会有热心玩家帮你解惑的:)

  • Linux/Mac用户,sudo vim /etc/hosts,在最后添加 xx.xx.xx.xx pkuxkx.net 即可。

不过用这种方式配置DNS解析的玩家需要注意,配置过后,如果你的MUD客户端里的IP地址栏填的是 pkuxkx.net 的话,那么MUD连接也会指向转发服务器的,这没有必要,还可能带来一些副作用,比如和他人共用IP带来的最大后遗症就是,连接MUD时可能显示:

你已经超过单IP允许的最大重复登陆数了。请合理使用服务器资源,谢谢!

产生这个现象的原因是,北侠服务器以为共用转发服务器的玩家都是从xx.xx.xx.xx登陆的,所以判断为同IP的登陆ID数过多。这时候,只需要把MUD客户端里的地址写成北侠的真实源地址(211.154.198.9)就能解决登陆限制的问题了。记得端口号写5555,因为8080端口目前也和80端口一样处于暂时悲剧中=.=

0x05 SSH端口转发

SSH,远程连接(Linux)服务器的必备利器,语言已经无法表达我对它的依赖之情了!其转发功能也非常强大,想要实现我们的功能,使用一条指令即可:

ssh -f -N -g -L 80:211.154.198.9:9999 root@localhost

解释下几个参数的作用:

  • -f:后台操作,只有当提示用户名密码的时候才转向前台。

  • -N:是不执行远端命令,在只是端口转发时这条命令很有用处。

  • -g:允许远端主机连接本地转发端口。

  • -L:将本地端口映射到远端主机端口。

总结一下这种用法的通用格式(除了-g和-L是必带参数,上面指令的其他参数都是锦上添花):

ssh -g -L [bind_addr:]port:host:hostport user@server

含义是将client机器上port端口流量通过server机器中转,转发到host机器的hostport端口(前面的例子中,client和server其实是一台机器,所以server指localhost)。

另外,需要修改代理服务器上的sshd设置,使其允许被远程访问,修改方法是编辑/etc/ssh/sshd_config,增加如下配置项:
GatewayPorts yes

本节内容实现的目标和之前的iptables是一样的,都是在某台Linux服务器上开启80端口,并将从80端口接收到的流量转发给 pkuxkx.net:9999,所以配合修改DNS解析配置食用,口感更佳。而这一实现目标,我们再来看Nginx是怎么做的。

0x06 Nginx端口转发

Nginx 最近两年好像很火的样子,发现网上不少文章,比如《Nginx开发从入门到精通》,开篇就讲Nginx架构而不提Nginx是什么,好像已经默认大家都懂这个了,果然是小编的层次太低吗T_T

Nginx可以说是(静态)Web Server,和老牌劲旅Apache的定位重合比较大,可以作为负载均衡里的前端服务器,用来处理请求的转发(反向代理等),将请求分配到比较空闲的后台服务。根据百度百科,Nginx “也是一个IMAP/POP3/SMTP服务器”,看上去好像很好玩。

先安装Nginx,Ubuntu系统下:

sudo apt-get install nginx

编辑配置文件:

vim /etc/nginx/conf.d/port_80_to_pkuxkx_9999.conf

server
{
    listen 80;
    server_name pkuxkx.net;
    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://211.154.198.9:9999;
    }
    access_log logs/pkuxkx_9999_access.log;
}

保存后重启下Nginx服务:service nginx restart

有一个问题:如果listen的端口号为80,生效后访问 http://xx.xx.xx.xx ,浏览器会显示一个Nginx的欢迎页而不是预期的北侠主页。研究 /etc/nginx/nginx.conf 后发现,配置文件中先 include 了 /etc/nginx/conf.d/*.conf 又 include 了 /etc/nginx/sites-enabled/* ,导致80端口相关配置被后来者覆盖。解决方案是将 include /etc/nginx/sites-enabled/* 注释掉,或者在这一行之后加入上面的配置项。

0x07 上篇小结

端口转发上篇就八到这里了。下篇可能整理下 Windows 下的端口转发、通用的脚本实现等。本来想一篇结束,但是文章越写越长,而且后面的内容有些目前还是很难hold得住。另外心里一点小愿望是,也许还没等我动笔,北侠的端口问题就解决了呢(辛苦冰神~ chat* massage icer),这样就可以省事儿了,grin……

如果北侠的朋友能从此文中真正了解甚至理解端口转发解决方案那再好不过;实在看不懂也没关系,这里将适用于北侠玩家的操作指南再总结一下,伸手党看这里:

  1. 最简单直接的方案,每次访问北侠网站(包括论坛、wiki、fullme图片等)直接在“pkuxkx.net”后面加9999端口号(再次强调端口号位置,不是在整个网址的最后,而是紧跟在“pkuxkx.net”后面)。这种方法下的wiki访问会比较慢而且缺少格式美化,请耐心等待。

  2. 如果想只输入 http://pkuxkx.net 就能访问北侠网站,那么就需要用管理员权限修改hosts文件,在C:\Windows\System32\drivers\etc\hosts里加一行xx.xx.xx.xx pkuxkx.net,然后重启浏览器。注意若使用这种方法,请只用转发ip访问网站,不要用这个IP连接MUD游戏(因为同一IP的登录ID数是有限制的),而需要手动在MUD客户端里将连接IP修改为211.154.198.9,端口号是5555。xx.xx.xx.xx = ?这个问题请进QQ群(群号152814678)或在MUD里chat询问,实在是由于某些原因不方便过于公开,chat* sorry。

最后写写感想:小编我之前实现端口转发,其实是自己写的python脚本,比较繁琐……借北侠端口故障的这个机会,了解并梳理一下当前几个比较成熟的轮子方案,也算不虚这么久的国庆节码字时光。对iptables、nginx几乎是第一次正式接触,SSH里的很多模糊概念也顺道明确了下,不过应该还会有不少bug和幼稚之处,欢迎指点(联系方式请关注订阅号”pkuxkx“,里面有订阅号的联系邮箱)。第一次在订阅号上写文,对读者的定位也不是很清晰,可能所描述内容前后的一致性很差,还请多包涵了。敲完这篇文章的时候,火车已经快要到北京了,嗯,那就顺便祝大家假期之后有一个好心情投入工作!chat* bow all

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/196700/viewspace-2136229/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-10-10

  • 博文量
    548
  • 访问量
    130254