2016年12月25日 星期日

請 raspberry pi 當網路門神

請 raspberry pi 當門神 前陣子先是 mirai 惡意程式碼遭公佈, 造成殭屍裝置大增, 不久之後又有 netgear 多款分享器大漏洞。 我研究室裡那部舊舊弱弱 (而且有 IP!) 的 router 不知有沒有被攻陷, 讓我好擔心。 該把它刷成 openwrt 或 dd-wrt 嗎? 要看型號跟運氣; 而且因為廠牌型號太多了, 開放原始碼的版本也很難保證持續更新。 煩惱一陣子之後, 決定買一部 raspberry pi 來擋在門口當門神。 至少完整的 linux 我比較知道如何防護及經常更新。 寧可暫時先犧牲網路速度, 換取安心睡覺的平靜。 本文適用於 raspbian 跟 archlinux ARM 兩個版本。

一、 準備

以下假設對外 (Internet) 的網卡名稱是 eth_ext, IP 是 123.45.67.89/24, gateway 是 123.45.67.254; 又假設對內 (LAN) 的網卡名稱是 eth_int, IP 是 192.168.59.1/24。 (它自己就是這個子網域的 gateway。)

正面迎向殘酷網路世界的門神, 當然然要穿上最強的盔甲。 所以請先把作業系統升級到最新:
raspbian: apt-get update ; apt-get upgrade
archlinux: pacman -Syu
此外, 應該先 幫 ssh 裝上 fail2ban 防護罩。 再來, 因為我們對外的網路會暫時不通, 所以建議先瞄一下後面要用到的指令, 如果有缺, 就先安裝。 最好乾脆先在你的主要工作電腦上面裝一顆 usb 無線網卡, 並且設定暫時改從手機走 3G/4G 上網, 因為等一下很可能會遇到臨時需要爬文或安裝套件的狀況。 再來, 因為我們會動到樹莓派的網路設定, 所以如果你本來是透過網路在操作它, 強烈建議最好先改成直接接上螢幕鍵盤, 以免等一下網路設壞了... 你就只好哭了! (我設壞過)

弱弱的 router: 先找到機體上的 「重置 (reset)」 按鈕, 長按五秒或十秒 (請查你的手冊), 讓它恢復原廠設定! 萬一先前真的被佔領變成僵屍, 這樣做這可讓它回魂。 重開機後, 取消它派送 dhcp 的功能, 以免跟樹莓派等一下的 dhcp 打架。 我連它的 wifi 也順手關掉了 -- 如果需要 wifi 的話, 請見文末連結 「用 raspberry pi 打造無線分享器」。 又, 先幫 router 設定一個 192.168.59.0/24 裡面的固定 IP, 以便等一下還沒設定 dhcp 時就可以先測試樹莓派的基本網路設定是否正確。

材料: 你需要一部 raspberry pi, 並且需要能夠接上兩條網路線。 例如我的樹莓派 3 有一個有線網路孔跟四個 usb 孔, 再上網搜尋 「usb rj45」 買到轉接頭, 就可以把其中一個 usb 孔變成網路孔。

接線: 把上游/外部網路的線接到樹莓派的其中一個網路孔, 再從另一個網路孔接線到 router, 但不要接在 router 上的 「Internet」 孔, 而要接在 LAN (內部網路) 的其中任何一個孔。 就是捨棄 router 的 routing 功能, 只把它當成一個 hub 來用。

二、 raspbian 版

一開始我採用的 OS 版本是購買時直接預載在 sdcard 上面的 raspbian。 (詳細版本待補)

先設定對外及對內網路。 把 /etc/network/interfaces 裡面, 關於 eth_ext 跟 eth_int 的部分修改成如下:

auto eth_ext
iface eth_ext inet static
  address 123.45.67.89
  gateway 123.45.67.254
  netmask 255.255.255.0
  dns-nameservers 8.8.8.8 8.8.4.4

auto eth_int
iface eth_int inet static
  address 192.168.59.1
  netmask 255.255.255.0

service networking restart, 唸一句祈福咒語, 然後按下 ENTER 重啟網路。 分別 ping 一下外網跟內網的機器 (例如弱弱的 router), 確認兩面的網路都設定成功。

再來安裝及設定 dhcp 伺服器: apt-get install isc-dhcp-serve 然後編輯 /etc/dhcp/dhcpd.conf, 在裡面加上:

subnet 192.168.59.0 netmask 255.255.255.0 {
  range 192.168.59.21 192.168.59.250;
  option broadcast-address 192.168.59.254;
  option routers 192.168.59.1;
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

還要在 /etc/default/isc-dhcp-server 裡面加上一句 INTERFACES="eth_int" 表示只對內網發送 dhcp 服務。 最後 service isc-dhcp-server restart 重啟 dhcp 服務。 在你的 (連在 router 上的) 主要工作電腦上, 停用無線網路、 重啟有線網路, 看有沒有被分配到 IP。

如果需要對特定網卡綁固定 IP 的話, 可以在 /etc/dhcp/dhcpd.conf 裡面加入類似這樣的設定:

host my_office_desktop {
  hardware ethernet ff;ee;dd;cc;bb;aa;
  fixed-address 192.168.59.5;
}

當然, 改完之後在樹莓派上要重啟服務、 在內網的其他電腦上必須斷線再連線, 才會生效。 現在主要工作電腦只能連區網, 無法連上 Internet。

再來設定 NAT, 叫樹莓派幫內網的機器轉寄封包, 這樣它們才能連上網際網路。 先在 /etc/sysctl.conf 裡面把這句: net.ipv4.ip_forward=1 打開生效。 (刪掉最前面的 #) [如果沒有重新開機的話, 可能要下 sysctl -p /etc/sysctl.d/30-ipforward.conf 才會生效?] 最後設定轉寄規則: 直接在命令列下:

iptables -t nat -A POSTROUTING -o eth_ext -j MASQUERADE
iptables -A FORWARD -i eth_ext -o eth_int -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth_int -o eth_ext -j ACCEPT

如果現在主要工作電腦又能夠連上 Internet, 那就成功了。 把轉寄規則存入設定檔: iptables-save > /etc/iptables.ipv4.nat 然後在 /etc/network/interfaces 裡面, iface eth_ext 的那一句底下補上一句: pre-up iptables-restore < /etc/iptables.ipv4.nat 這樣下次重開機 (或下過 service networking restart 之後) 系統就會自動重新載入轉寄規則。

三、 archlinux 版

後來我的樹莓派改灌 Arch Linux ARM。

先設定對外及對內網路。 在 /etc/systemd/network 底下, 建立兩個設定檔, 分別是 eth_ext.network:

[Match]
Name=eth_ext

[Network]
Address=123.45.67.89/24
Gateway=123.45.67.254

以及 eth_int.network:

[Match]
Name=eth_int

[Network]
Address=192.168.59.1/24

systemctl restart systemd-networkd, 唸一句祈福咒語, 然後按下 ENTER 重啟網路。 分別 ping 一下外網跟內網的機器 (例如弱弱的 router), 確認兩面的網路都設定成功。

再來安裝及設定 dnsmasq: pacman -S dnsmasq 然後編輯 /etc/dnsmasq.conf , 在裡面加上:

interface=eth_int
dhcp-range=192.168.59.21,192.168.59.250,12h

最後 systemctl restart dnsmasq 重啟 dnsmasq 服務。 在你的 (連在 router 上的) 主要工作電腦上, 停用無線網路、 重啟有線網路, 看有沒有被分配到 IP。 如果成功的話, 還要 systemctl enable dnsmasq 這樣以後每次重開機才會自動啟動。 (因為在 archlinux 裡, 安裝新服務並不會自動直接啟用。)

如果需要對特定網卡綁固定 IP 的話, 可以在 /etc/dnsmasq.conf 裡面加入類似這樣的設定: dhcp-host=ff:ee:dd:cc:bb:aa,192.168.59.5 當然, 改完之後在樹莓派上要重啟服務、 在內網的其他電腦上必須斷線再連線, 才會生效。 現在主要工作電腦只能連區網, 無法連上 Internet。

再來設定 NAT, 叫樹莓派幫內網的機器轉寄封包, 這樣它們才能連上網際網路。 先安裝 iptables: pacman -S iptables 再來設定每次重開機之後都要啟用轉寄功能: 把以下內容貼入 (原本可能不存在的) 設定檔 /etc/sysctl.d/30-ipforward.conf :

net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1

[如果沒有重新開機的話, 可能要下 sysctl -p /etc/sysctl.d/30-ipforward.conf 才會生效?] 最後設定轉寄規則: 直接在命令列下:

iptables -t nat -A POSTROUTING -o eth_ext -j MASQUERADE
iptables -A FORWARD -i eth_ext -o eth_int -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth_int -o eth_ext -j ACCEPT

如果現在主要工作電腦又能夠連上 Internet, 那就成功了。 把轉寄規則存入設定檔: iptables-save > /etc/iptables/iptables.rules 然後用 systemctl status iptables 確認 iptables 服務有啟動 (active)。 如果沒有 active 的話, 要 (把上句的 status 分次換成) enable 跟 start 。

四、 雜記

本文主要參考 G. T. Wang 大大的文章: 樹莓派 Raspberry Pi 設定無線網路 WiFi AP,打造無線 IP 分享器, 修正其中一些打字錯誤並簡化。 Archlinux 的部分爬太多文了, 連結省略。 沒關係, 他們的文件寫得太好了, 就算你是想解決 lubuntu/debian 上面的問題都可能不小心會搜尋到 archlinux 的文件。

我買 usb <==> rj45 轉接頭的時候, 買到 usb 2.0 的版本。 如果改用 usb 3.0 的版本, 速度應該快很多。

設定完全成功之後, 最好重開機一次, 確認設定有保留。

為什麼我要改用 archlinux? 因為在 raspbian 底下想玩 lxc 一直失敗, 爬文時在某處 (找不到連結了) 讀到: 改用 archlinux 就成功了。 (版本夠新的意思吧。) 總之我為了資訊安全而入手第一部 raspberry pi; 又為了玩 lxc 而第一次安裝 archlinux, 這真是奇妙的緣份啊!

本文是根據設定檔及 .bash_history 回憶出來的, 如有疏漏, 請留言分享或提問囉。

2 則留言:

  1. Hello 請教一下
    你最後這台ROUTER 有辦法support IPV6麼 ?
    下面的電腦上ipv6 test網站有辦法通過麼

    回覆刪除
    回覆
    1. 我連終端的電腦都沒設定過 ipv6 耶 (艸) 該回籠重修網路課了...

      刪除

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。