端口也是我们通信识别的关键信息,掌握好各个端口的使用方式对我们编程很关键。

常用端口

1、知名端口

知名端口即众所周知的端口号,范围从0到1023,这些端口号一般固定分配给一些服务。比如21端口分配给FTP服务,25端口分配给SMTP(简单邮件传输协议)服务,80端口分配给HTTP服务,135端口分配给RPC(远程过程调用)服务等等。

2、动态端口

动态端口的范围从1024到65535,这些端口号一般不固定分配给某个服务,也就是说许多服务都可以使用这些端口。只要运行的程序向系统提出访问网络的申请,那么系统就可以从这些端口号中分配一个供该程序使用。比如1024端口就是分配给第一个向系统发出申请的程序。在关闭程序进程后,就会释放所占用的端口号。

但是我们一般不会指定使用1024-5000的端口,因为系统端口都是重1024开始默认递增使用的,所以我们自定义的端口都是重5001开始的,比如prometheus的9099等。

端口复用

使用场景

  • 1)服务器只对外开放某一端口(80端口或其他任意少量端口),其他端口全部被封死
  • 2)为了躲避防火墙
  • 3)隐藏自己后门
  • 4)转发不出端口
  • 5)内网渗透(如:当当前服务器处于内网之中,内网IP为10.10.10.10开放终端登录端口但并不对外网开放,通过外网IP:111.111.111.111进行端口映射并只开放80端口,通过端口复用,直连内网)。

实现

端口复用,不能用一般的socket套接字直接监听,这样会导致程序自身无法运行,或者相关占用端口服务无法运行,所以,办法暂时只有在本地做些手脚。

1、端口重定向

在本地建立两个套接字sock1、 scok2,scok1监听80端口,当有连接来到时, Sock2连接重定向端口,将Sock1接收到的数据加以判断并通过 Sock2转发。这样就能通过访问目标机80端口来连接重定向端口了。

2、端口复用

在本地建立一个监听和本地开放一样的端口如80端口,当有连接来到时,判断是否是自己的数据包,如果是则处理数据,否则不处理,交给源程序。正常我们使用http端口复用,比如nginx的方向代理不同服务,可以根据host+url来处理具体请求到后端,这个使用可以在nginx机器上复用一个端口,其实就是根据数据,来转发处理。但是这个并不是什么协议都等实现的,比如tcp协议,你就不知道该放倒后段什么操作中。socket本身的端口复用参数,只是用于解决一些连接结束但是未结束重用的问题。

http等应用层协议是在tcp协议的报文体,解析后可以得知一些host或者url等信息,可以根据这个分发到具体的不同服务处理,所以一个连接,也即是端口绑定,可以处理多种类型的服务,起到了端口复用的作用,比如nginx前置服务器,然后针对tcp协议,正常就是端口被绑定后就不能再去绑定了,不可以复用,当然后来tcp,协议也开启了对应参数可以对同一个socket的ip和port进行多重绑定,但是只是为了处理连接复用的问题,防止连接被占用,其实起作用的就是最后一个连接有数据。

frp中的端口复用:其实就是一般的nginx后端处理方式,但是是以tcp的监听为对外的入口,重写了accept,重队列中获取对应的conn,对不同的协议进行区分,如果是http,则按http请求后端处理。