erlang的epmd指定端口范围验证及端口权限配置

erlang的epmd指定端口范围验证及端口权限配置

1,简介   

        erlang的原理与linux系统很是像,有进程的概念,有进程调度等。今天要验证的就是相似于DNS的功能:epmd。epmd是Erlang Port Mapper Daemon的缩写,用于Erlang集群中的节点互通。好比在ip1上面启动了一个节点 nodeA@ip1,在ip2上面启动了一个节点nodeB@ip2,若是nodeA要访问nodeB,那么首先会去connect nodeB节点上的epmd服务的端口:4369 端口,他会告诉nodeA,nodeB@ip2是在哪一个端口,而后nodeA直接connect该端口,与nodeB进行通讯。若是nodeB想要与nodeA通讯,因为nodeA已经于nodeB创建了链路,那么直接使用该链路进行通讯,不然也要像nodeA同样,先访问nodeA的4369端口,获取nodeA的监听端口,而后访问该端口。关于epmd的原理和使用,有不少写的很好的文章,好比[Erlang 0123] Erlang EPMD,Erlang epmd的角色以及使用,建议读者能够先看一下这篇文章:[Erlang 0123] Erlang EPMD,本文只是单纯的验证-kernel inet_dist_listen_min PortMin inet_dist_listen_max PortMax的正确性,而后讲解一下遇到的防火墙配置问题,最后总结一下在生产环境应该如何开通访问权限。由于生产环境遵循最小权限的原则,因此须要对端口权限控制的很是精准。在如rabbitmq、couchbase这样的erlang应用中都会用到。html

2,结论

    咱们先说一下结论:
    首先在192.168.3.142机器上面启动一个节点'test142@192.168.3.142',而后在另一台机器192.168.3.140上面启动一个节点'test140@192.168.3.140',上面部署了一个使用erlang代码编写的web监控程序,须要监控节点'test142@192.168.3.142'的运行状况。此时就须要这两个节点之间可以连通。显然局域网中是很容易实现的,没有太多的端口限制。可是若是'test142@192.168.3.142'是部署在生产环境内的局域网,'test140@192.168.3.140'是部署在DMZ区,他们之间的访问就涉及到端口权限的开通。首先须要140申请访问142的epmd-4369端口,这样才能查到test142节点的监听端口。(为保障生产环境的安全,除非必要,通常不会反向开通142到140的4369端口。)而后142的4369端口会告诉140,节点'test142@192.168.3.142'监听的端口,一般这是一个随机端口。这样140还须要再申请到142的随机端口的访问,这显然是不现实的。因此erlang提供了一个解决办法:固定test142节点的监听范围,而不让他变成随机端口。node

erl -kernel inet_dist_listen_min 44000 inet_dist_listen_max 44002 -name test142@192.168.3.142 -setcookie test

    在192.168.3.142机器上面执行该命令,设置该节点启动以后,监听的端口为44000,若是44000被占用,那么监听44001,若是依然被占用,那么监听44002,若是还被占用,那么报错。这样140只须要开通到142上44000~44002的端口权限就能够了。因此申请的端口列表是:linux

src:192.168.3.140    to:192.168.3.142     port:4369web

src:192.168.3.140    to:192.168.3.142     port:44000shell

src:192.168.3.140    to:192.168.3.142     port:44001centos

src:192.168.3.140    to:192.168.3.142     port:44002安全

    那么从'test140@192.168.3.140'访问'test142@192.168.3.142'的链路是通的,可是从'test142@192.168.3.142'到'test140@192.168.3.140'的链路是否也通呢?若是你在142机器上面执行cookie

net_adm:ping('test140@192.168.3.140').

    获得的结果是"pang",也就是不通。难道必须开通反向的从142到140的端口吗?其实不用,咱们先在140机器上面执行app

net_adm:ping('test142@192.168.3.142').

    获得的结果是"pong",这是正常的,由于咱们已经开通了从140到142的4369和44000的权限。此时再去142机器上执行net_adm:ping('test140@192.168.3.140').  会发现获得的结果是"pong",竟然通了!咱们不须要再开通反向的端口权限就解决了这个问题。这样能最大限度的减小端口的开通。因此在生产环境中咱们只须要开通上面4个端口权限便可。   ssh

    到这里结论已经出来了,若是读者愿意继续看,下面是个人验证过程,涉及到防火墙的配置,若是没兴趣,到这里就能够结束了。

3,验证过程

    192.168.3.140和192.168.3.142都是个人Centos虚拟机。为了将192.168.3.142模拟成生产环境,我将142机器上面的全部端口都屏蔽:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

    关于iptables 防火墙的操做,你们能够参考这个:linux IPtable防火墙 禁止和开放端口,讲得很是详细。若是iptables命令不可用,出现相似于这样的错误

The service command supports only basic LSB actions (start, stop, restart, try-restart, reload, force-reload, status). For other actions, please try to use systemctl.

或者出现异常,能够参考这个解决:关于centos 7 中service iptables save 指令使用失败的结局方案 。若是读者是在xshell这样的ssh软件里面执行上面的操做,那么执行到中途就会发现ssh链接断开了,由于ssh的22号端口已经被防火墙屏蔽了,因此建议你们直接在虚拟机中执行上面三条命令。而后,为了方便输入,咱们能够打开22号端口,输入如下命令:

iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT

第一条准入命令,表示容许其余机器准入,协议是tcp,目的端口是22,注意这个是单向的,即只容许其余机器向142的22端口发送数据,可是不容许22端口回复数据,因此此时ssh其实仍是不可用,咱们还须要加上下面那一条,容许准出:容许本机从22端口发出tcp数据包。这样咱们就可使用xshell这样的软件方便使用了。

  • 首先容许140访问142的4369端口,执行以下命令:
  • iptables -A INPUT -p tcp -s 192.168.3.140 --dport 4369 -j ACCEPT
    iptables -A OUTPUT -p tcp -d 192.168.3.140 --sport 4369 -j ACCEPT

    第一条是准入命令:容许源ip地址为192.168.3.140的机器,向本机的4369端口发送tcp的数据包,一样这也是单向的,因此必须加上第二条准出命令:容许本机的4369端口先目的ip地址为192.168.3.140的机器发送tcp数据包,这样才能保证顺畅的访问4369端口。此时在140机器上面telnet 142 的4369 端口是通的。

  • 因为咱们不知道未来142节点启动以后会是44000~44002中的哪个(由于其中的端口有可能被其余应用程序占用),因此正常状况下咱们会开通44000~44002之间的全部端口
  • iptables -A INPUT -p tcp -s 192.168.3.140 --dport 44000 -j ACCEPT
    iptables -A OUTPUT -p tcp -d 192.168.3.140 --sport 44000 -j ACCEPT
    iptables -A INPUT -p tcp -s 192.168.3.140 --dport 44001 -j ACCEPT
    iptables -A OUTPUT -p tcp -d 192.168.3.140 --sport 44001 -j ACCEPT
    iptables -A INPUT -p tcp -s 192.168.3.140 --dport 44002 -j ACCEPT
    iptables -A OUTPUT -p tcp -d 192.168.3.140 --sport 44002 -j ACCEPT
  • 此时咱们尝试在142机器上面启动test142节点:
    erl -kernel inet_dist_listen_min 44000 inet_dist_listen_max 44002 -name test142@192.168.3.142 -setcookie test

    你会惊讶的发现启动不了,命令一直卡在那里不动,什么缘由呢?由于142机器上面的端口权限,只开通了上面几个,其余全部的端口都是禁止的,包括142访问142本身的端口,也一样是禁止的,没法访问!erlang在启动的时候,须要访问本地的端口的,因此应该容许142机器拥有访问自己的权限:

    iptables -A INPUT -s 127.0.0.1 -j ACCEPT
    iptables -A OUTPUT -d 127.0.0.1 -j ACCEPT

    一样,也是两条命令,一条准入,一条准出,一条都不能少。按照理解,第一条准入命令与第二条准出命令是等价的,好像只有一条就能够。可是我试过删除第二条准出命令,只留下第一条准入命令,依然是卡在那里不动,因此两条命令一条都不能少。在142上面执行

  • iptables -L -n

    查看一下当前的防火墙配置,能够看到以下的防火墙规则:

  • 执行以下命令查看本机当前的全部erlang节点所监听的端口

  • epmd -names

    能够看到"name test142 at port 44000"的提示,说明test142节点已经监听在了44000端口

  • 在142机器的erl界面里执行ping 命令用以测试是否与140节点连通,能够看到结果为"pang",是通不了的。

  • net_adm:ping('test140@192.168.3.140').

  • 而后在140机器上面启动一个erlang节点,

  • erl -name test140@192.168.3.140 -setcookie test

    而后测试与142节点是否连通,能够看到结果是"pong",是能够通的

  • 此时再在142机器的erl界面里执行ping 命令用以测试是否与140节点连通,能够看到结果为"pong",已经连通,由于上一步test140节点已经建好了一条链路,因此能够连通。
    至此,在知足最小端口权限的原则下,已经打通了两个节点之间的通讯链路。

相关文章
相关标签/搜索