在MacOS上使用1024以下端口

起因

MacOS和Linux一樣,需要root權限使用低于1024以下端口。因此要在Mac機器上監(jiān)聽80端口或443端口,要么以root用戶啟動應用,要么使用端口轉(zhuǎn)發(fā)。

在Linux系統(tǒng)中可以通過sudo setcap cap_net_bind_service=+ep <app name>來讓非root用戶使用1024以下端口(<app name>指要授權監(jiān)聽端口的程序)。

MacOS沒有setcap命令,所以需要通過端口轉(zhuǎn)發(fā)來達到目的。新版的MacOS操作系統(tǒng)使用pf(packet filter)設置端口轉(zhuǎn)發(fā)。

簡單粗暴的解決方式

echo "
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
rdr pass inet proto tcp from any to any port 443 -> 127.0.0.1 port 8443
" | sudo pfctl -ef -

rdr: The packet is redirected to another destination and possibly a different port.
數(shù)據(jù)包被重定向到另一個目的地,可能還有一個不同的端口
rdr rules can optionally specify port ranges instead of single ports.
規(guī)則可以選擇指定端口范圍而不是單個端口
rdr ... port 2000:2999 -> ... port 4000 redirects ports 2000 to 2999 (inclusive) to port 4000.
... port 2000:2999 -> ... port 4000 重定向端口2000-2999(包含2999)到端口4000
rdr ... port 2000:2999 -> ... port 4000:* redirects port 2000 to 4000, 2001 to 4001, ..., 2999 to 4999.
... port 2000:2999 -> ... port 4000:* 重定向端口2000到端口4000,端口2001到端口4001,...,端口2999到4999

比較詳盡的管理方式

創(chuàng)建anchor文件

??注意,以下示例端口有重復。
示例一:
/etc/pf.anchors/http

rdr pass on lo0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
rdr pass on lo0 inet proto tcp from any to any port 443 -> 127.0.0.1 port 4443
rdr pass on en0 inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
rdr pass on en0 inet proto tcp from any to any port 443 -> 127.0.0.1 port 4443

示例二:
/etc/pf.anchors/tomcat

rdr pass on lo0 inet proto tcp from any to 127.0.0.1 port 80 -> 127.0.0.1 port 8080

示例三:
/etc/pf.anchors/virtualbox

rdr pass on lo0 inet proto tcp from any to 127.0.0.1 port 80 -> 127.0.0.1 port 8080
rdr pass on lo0 inet proto tcp from any to 127.0.0.1 port 443 -> 127.0.0.1 port 8443

測試anchor文件

pfctl -vnf /etc/pf.anchors/http
pfctl -vnf /etc/pf.anchors/tomcat
pfctl -vnf /etc/pf.anchors/virtualbox

添加到主配置文件

pf啟動時會自動裝載/etc/pf.conf文件,因此將anchor文件鏈接到/etc/pf.conf,轉(zhuǎn)發(fā)規(guī)則就會自動建立了。pf.conf 對指令的順序有嚴格要求,相同的指令需要放在一起,否則會報錯 Rules must be in order: options, normalization, queueing, translation, filtering.

rdr-anchor "http-forwarding"
load anchor "http-forwarding" from "/etc/pf.anchors/http"

rdr-anchor "tomcat-forwarding"
load anchor "tomcat-forwarding" from "/etc/pf.anchors/tomcat"

rdr-anchor "virtualbox-forwarding"
load anchor "virtualbox-forwarding" from "/etc/pf.anchors/virtualbox"

打開pf

pf默認是關閉的。可以使用以下命令啟動pf:

sudo pfctl -ef /etc/pf.conf

使用 -e 命令啟用 pf 服務。使用 -E 命令強制重啟 pf 服務:

$ sudo pfctl -E

關閉pf

使用 -d 命令關閉 pf:

$ sudo pfctl -d

設置pf自啟動

修改 LaunchDaemons (《了解LaunchDaemons》)來使 pf 開機自動打開

<key>ProgramArguments</key>
<array>
<string>pfctl</string>
<string>-e</string>
<string>-f</string>
<string>/etc/pf.conf</string>
</array>

添加的為-e參數(shù),即enable。 有一點一定要注意,-f和etc/pf.conf這兩個參數(shù)不能被打斷,因為-f必須緊跟一個文件參數(shù),所以說添加-e參數(shù)時不要打斷-f參數(shù),否則開機不會自動啟動pf,切記。

跨接口轉(zhuǎn)發(fā)

如果需要跨接口轉(zhuǎn)發(fā),則需設置系統(tǒng)參數(shù): /etc/sysctl.conf
開機啟動配置,需以 root 身份添加或修改 /etc/sysctl.conf 文件,加入以下兩行:

net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1

跨接口轉(zhuǎn)發(fā),本次開機生效:

  • IPv4 的轉(zhuǎn)發(fā)
$ sudo sysctl -w net.inet.ip.forwarding=1
net.inet.ip.forwarding: 0 -> 1
  • IPv6 的轉(zhuǎn)發(fā)
$ sudo sysctl -w net.inet6.ip6.forwarding=1
net.inet6.ip6.forwarding: 0 -> 1

查看當前轉(zhuǎn)發(fā)狀態(tài)

$ sudo sysctl -a | grep forward
net.inet.ip.forwarding: 0
net.inet6.ip6.forwarding: 0

幫助手冊

開啟端口轉(zhuǎn)發(fā)之后,即可配置端口轉(zhuǎn)發(fā)規(guī)則。你可以跟著手冊來:

$ man pfctl
$ man pf.conf
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。