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節點已經建好了一條鏈路,因此能夠連通。
    至此,在知足最小端口權限的原則下,已經打通了兩個節點之間的通訊鏈路。

相關文章
相關標籤/搜索