raspberrypi 官網 raspberrypi 官網

互動 IoT 系統應用 - 上課教材

互動 IoT 系統應用 > 課程內容 > 第 15 章 - 使用樹莓派建立無線 AP 與樹莓派藍芽

第 15 章 - 使用樹莓派建立無線 AP 與樹莓派藍芽

上次更新日期 2022/12/18

目前 (2022) 的無線 AP 技術使用到非常高速的 wifi-6 或 wifi-7 了!而且無線 AP 的價格也很低,說實在的, 沒有道理使用樹莓派來做成 AP 的價值!因為樹莓派又貴,wifi 速度搭配有線網路效率也不高。不過,有個很現實的目的, 那就是,你可能要使用樹莓派當作中繼站,讓你的許多類似 arduino 的 IoT 設備連上來,甚至進一步取得距離訊號的資訊, 以了解 IoT 的設備距離你的樹莓派多遠。這時,就有可能需要透過樹莓派的無線網卡模擬成為無線 AP 的功能了!

學習目標:

  1. 了解整體網路架構
  2. 設定樹莓派無線網卡
  3. 了解使用 nmcli 指令列模式處理相關任務
  4. 增加藍芽的應用

15.1: 要使用無線 AP 的網路連線情境

如果你有搭建過無線基地台 (Access point, AP) 的設備,就會知道無線 AP 後面通常會有兩種埠口,一種稱為 WAN 一種稱為 LAN, 其中 WAN 會要求你連線到電信商的數據機上面,而 LAN 就是直接當成區域內有線網路使用。另外,無線 AP 會提供 wifi 無線技術, 讓其他支援 wifi 的機器可以連接到這台 AP 上面,然後透過 WAN 的埠口來達成對外連線。當然啦,我們的 AP 需要具備路由器功能, 這就得要啟動防火牆的 NAT (網路位址轉換) 功能才可以。我們可以簡單使用底下的圖示來說明:

樹莓派課程 (圖示來源:https://blog.jsy.tw/2288/wireless-router-six-modes/)

你會發現,AP 的左手邊會連到 internet 上,當然這邊就需要一條實體網路線,右邊則是無線網路,所以需要一個無線網卡! 呵呵!剛剛好,我們的樹莓派,左側就是一個實體的 RJ-45 接頭的網路線,右側則是無線網卡!沒錯!剛剛好可以做成無線 AP 啦!

例題 15.1.1:取得另外一個網路界面:
  • 實體線路:
    請拿出 RJ-45 網路線,連結到相關的網路孔之後,查看樹莓派上面的網路卡燈號是否有亮燈, 一定要有亮燈才是連結到有連線的網路媒體上。
  • 網路位址參數處理:
    假設你的環境裡面是有 DHCP 伺服器 (自動分配網路參數服務) 的功能, 因此你必須要設定實體網卡成為自動取得網路參數的方式才行。詳細的指令請參考第三章的內容,最終使用 『 ip addr show eth0 』時,必須要出現網路位址參數才行。
  • 無線 AP 或無線路由器所需要的服務

我們的手機、使用無線網路的樹莓派、無線印表機、平板電腦等,大多使用 wifi 連接到 AP 之後,無須自行設定網路參數, 就可以上網了!這是因為無線 AP 裡面通常會具備底下幾個服務,提供 wifi 用戶端的網際網路連線功能:

  • 無線存取連結: 提供 SSID, 連線密碼等服務,讓使用者可以授權使用此 AP 的連線;
  • 自動分配網路參數服務: 提供用戶端自行設定好 IP 位址、通訊閘、DNS 伺服器位址等功能;
  • 防火牆轉遞: 讓用戶端可以從另外一個網路界面連線出去的轉遞功能。

所以,我們的樹莓派想要變成無線 AP 的網路服務提供者,就需要完成上述的功能設定才行! 不過,有個很簡單的方式,那就是直接透過 NetworkManager 來處理!這個 NetworkManager 會主動的幫忙設定好所有項目, 包括 SSID、連線密碼、繞過防火牆機制等,都非常非常簡單!那就讓我們來處理一下這東西!

15.2: 使用 NetworkManager 設定 AP

我們要將樹莓派的無線網卡設定成為 AP,又因為我們之前已經使用了 nmcli 作為管理網路的主要軟體, 所以,底下的方法,我們都使用 nmcli 來達成!如果你的樹莓派並沒有依據我們之前第三章的方法進行設計, 那就請參考其他文件喔!

  • 確定硬體存在與否

首先,我們先來看看你的系統有沒有無線網路,同時,無線網路有沒有啟動!如下所示:

$ nmcli general status
STATE   CONNECTIVITY  WIFI-HW  WIFI    WWAN-HW  WWAN
已連線  已滿          已啟用   已啟用  已啟用   已啟用

# 若要啟動/關閉 wifi ,可以這樣做:
$ sudo nmcli radio wifi [on|off]

這樣就確定 wifi 硬體存在之外,這個硬體也是啟用的!如此才能夠繼續下一步。

  • 建立 Wifi AP 名稱、網路設定等

我們預計提供的網路參數為如下的設定:

  1. 無線網卡的模式 (mode) 為 ap,且 IP 位址預計為: 192.168.33.254/24
  2. 無線網卡的連線名稱與 SSID 都是 RPi-vbird (這個請自行修改)
  3. 使用的頻譜協定為 802.11bg
  4. 使用的加密機制為 wpa-psk
  5. wpa 的連線密碼使用 062727175 這一個 (密碼長度需要在 8~63 個字元間)
  6. IP 的方法 (method) 為分享

接下來可以這樣做:

# 1. 2. 建立 RPi-vbird 連線名稱與 SSID 相關資料,以及 IP 位址設定:
$ sudo nmcli connection add type wifi mode ap con-name RPi-vbird ifname wlan0 \
> ssid RPi-vbird ipv4.addresses 192.168.33.254/24

# 3. 使用 802.11bg 頻譜
$ sudo nmcli connection modify RPi-vbird 802-11-wireless.band bg

# 4. 使用 wpa-psk 加密機制
$ sudo nmcli connection modify RPi-vbird 802-11-wireless-security.key-mgmt wpa-psk

# 5. 修改 RPi-vbird 的連線密碼
$ sudo nmcli connection modify RPi-vbird 802-11-wireless-security.psk 062727175

# 6. IP 位址的方法為分享:
$ sudo nmcli connection modify RPi-vbird ipv4.method shared

# 建立完成後,啟動 RPi-vbird
$ sudo nmcli connection up RPi-vbird

# 最後確認一下 IP 位址是否正確處理了:
$ ip addr show wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP ..
    link/ether b8:27:eb:d8:ae:89 brd ff:ff:ff:ff:ff:ff
    inet 192.168.33.254/24 brd 192.168.33.255 scope global noprefixroute wlan0
       valid_lft forever preferred_lft forever
    inet6 fe80::2543:7361:44c9:d3e8/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

如果你突然忘記連線的 SSID 等相關資料時,有個簡單的方法可以查詢:

$ sudo nmcli device wifi show-password
SSID: RPi-vbird
安全: WPA
密碼: 062727175
....

這樣,你的無線網卡以及相關的 SSID 與連線密碼就搞定了!連同防火牆、

  • 其他相關設定檔:

基本上,跟 NetworkManager 有關的檔案,大致上有底下的目錄或檔案,有興趣的朋友可以自行去瞧瞧,我們這裡不再深究。

  • /etc/NetworkManager/NetworkManager.conf: NetworkManager 的主要設定檔
  • /etc/NetworkManager/system-connections/: 每個連線的詳細設定值在這裡!
  • /var/log/daemon.log: 登錄檔其實放在這裡!有問題可以來查查看
  • /etc/resolv.conf: 其實是 DNS 伺服器 IP 的儲存檔案
  • /etc/sysctl.conf: 主要是設定 ip_forward 的重要檔案!
  • /var/lib/NetworkManager/dnsmasq-wlan0.leases: 查詢用戶端取得 IP 位址的資訊

15.3: 其他查詢檢驗

基本上,上述的 nmcli 相關指令做完之後,你的無線 AP 其實已經完成了!無須進行其他設定了! 只是,如果出了點問題,導致你的 wifi 用戶端無法連上的話,那就得要做點檢查才行!這時,我們可以這樣進行一些簡單的檢查行為:

  • 檢查 wifi 網卡的參數

如果 wifi 網卡本身設定就錯誤了,那就肯定會有點問題吧!所以,先來檢查一下設定!先看一下設定檔, 設定檔內容應該會有點像這樣:

$ sudo cat /etc/NetworkManager/system-connections/RPi-vbird.nmconnection
....
[wifi]
band=bg
mac-address-blacklist=
mode=ap
ssid=RPi-vbird

[wifi-security]
key-mgmt=wpa-psk
psk=062727175

[ipv4]
address1=192.168.33.254/24
dns-search=
method=shared
....

基本上,出現上面的幾個關鍵字,應該問題就不是太大!你也可以使用 nmcli 去查看相關資料:

$ nmcli connection show RPi-vbird
$ nmcli connection show RPi-vbird | egrep 'ssid|mode|band|key-mgmt|methd|addresses'
802-11-wireless.ssid:                   RPi-vbird
802-11-wireless.mode:                   ap
802-11-wireless.band:                   bg
802-11-wireless-security.key-mgmt:      wpa-psk
ipv4.addresses:                         192.168.33.254/24

快速檢查一下設定值,看看有沒有問題呢!

  • 查看路由器功能以及路由表

要能夠進行 IP 轉遞的路由器功能,必須要啟用一個名為 ip forward 的核心功能!查詢方式如下:

$ cat /proc/sys/net/ipv4/ip_forward
1

回傳的訊息中,若為 1 ,代表功能啟動,若為 0 則是該功能沒有啟動!這個功能一定要啟動,不然, 所有的 AP 功能都不會生效!如果你發現該設定是 0 的時候,就得要手動編輯一下這個檔案,同時啟動它了!

# 1. 編輯設定檔成為底下的模樣:
$ sudo vim /etc/sysctl.conf
net.ipv4.ip_forward=1

# 2. 讓這個設定實際啟動!
$ sudo sysctl -p
net.ipv4.ip_forward = 1

這樣就完成了所謂的 IP 轉遞的核心功能!!

  • 確認 DNS IP 位址

有的時候如果不小心對 NetworkManager 的設定資料錯誤,可能會導致 DNS 伺服器 IP 位址的改變! 要檢查 DNS IP 位址,就得要查看 /etc/resolv.conf 了!同時注意到埠口的變化!你可以這樣檢查:

# 1. 檢查埠口
$ sudo netstat -tulnp | grep dnsmasq
tcp        0      0 192.168.33.254:53   0.0.0.0:*    LISTEN      2830/dnsmasq
udp        0      0 192.168.33.254:53   0.0.0.0:*                2830/dnsmasq
udp        0      0 0.0.0.0:67          0.0.0.0:*                2830/dnsmasq

# 2. 檢查 DNS 伺服器 IP
$ cat /etc/resolv.conf
nameserver 168.95.1.1
nameserver 8.8.8.8

你的 wifi 用戶端使用的 DNS 伺服器 IP 位址參考,就是使用上面的 /etc/resolv.conf 檔案內容! 而該檔案內容卻是由 nmcli connection show 裡面的 eth0 所指定的 (可能是 dhcp 來的,可能是手動指定), 無論如何,你應該要修改的是 eth0 的設定,不要直接改 /etc/resolv.conf 才對!另外, wifi 的 AP 模式會主動提供 DHCP 喔! 所以,我們得來查詢一下!參考下一點的說明。

  • 查詢 dhcp 是否提供相關功能

上一小點如果你仔細看,會看到一個 port 67 的埠口,這個埠口就是提供 dhcp 功能的埠口了!一般來說, dnsmasq (network manager 主動喚醒) 會提供整個網段的可用 IP 給 wifi 用戶端!如何查詢呢? 可以看 /var/log/daemon.log 的內容,詳細查詢,會有點像這樣:

$ sudo grep dnsmasq-dhcp /var/log/daemon.log
 dnsmasq-dhcp[5101]: DHCP, IP range 192.168.33.1 -- 192.168.33.245, lease time 1h
 dnsmasq-dhcp[5101]: DHCPDISCOVER(wlan0) 46:b6:a7:35:eb:f1
 dnsmasq-dhcp[5101]: DHCPOFFER(wlan0) 192.168.33.229 46:b6:a7:35:eb:f1
 dnsmasq-dhcp[5101]: DHCPREQUEST(wlan0) 192.168.33.229 46:b6:a7:35:eb:f1
 dnsmasq-dhcp[5101]: DHCPACK(wlan0) 192.168.33.229 46:b6:a7:35:eb:f1 somename

如上,可以看到提供的 IP 位址範圍,還能看到最近一個登入我們 wifi 的用戶所取得的 IP 呢!

  • 防火牆的查詢與設定 (如放行 ssh port)

事實上,我們的 wifi AP 功能,也需要透過 Linux 核心的防火牆轉遞功能才行! 這個轉遞功能使用的方式稱為偽裝『 MASQUERADE 』!你的防火牆應該會有這個功能才對!檢查看看:

$ sudo iptables-save | grep -i masquerade
-A POSTROUTING -s 192.168.33.0/24 ! -d 192.168.33.0/24 -j MASQUERADE

如果有出現類似上面的這個規則,那應該防火牆設計就沒有問題!如果沒有這行,那就代表你的 nmcli 設定可能有問題喔! 需要回頭重新設定一下才好!另外,我們防火牆不是使用 ufw 嘛?為什麼這裡會用到 iptables 呢? 這是因為 ufw 只是一個簡單的管理界面,事實上所有的防火牆功能,都是 iptables 這個核心機制 (netfilter) 完成的! 所以,我們確實可以透過 iptables 去查詢喔!

上面的設定中,其實有個困擾!那就是,wifi 用戶端可以向外面連線,但是卻無法使用 ssh 連線到樹莓派! 這是因為我們沒有啟用防火牆放行的功能啊!現在,你可以這樣進行,讓 wifi 用戶端能夠登入你的樹莓派 ssh 埠口!

$ sudo ufw allow from 192.168.33.0/24 to any port ssh
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
80/tcp                     ALLOW       Anywhere
Anywhere                   ALLOW       192.168.0.0/16
22/tcp                     ALLOW       172.31.0.0/16
Samba                      ALLOW       10.0.0.0/8
21/tcp                     ALLOW       Anywhere
22/tcp                     ALLOW       192.168.33.0/24
80/tcp (v6)                ALLOW       Anywhere (v6)
21/tcp (v6)                ALLOW       Anywhere (v6)

15.4: 樹莓派藍芽功能

樹莓派本身是有支援藍芽的,不過,我們可能需要事先安裝一個名為 bluez 的軟體,這個軟體才有辦法提供許多額外的藍芽控制功能。 基本上,這個軟體應該是有在預設安裝的名單內,如果沒有的話,沒關係!我們就來手動安裝一下:

 $ sudo apt-get install bluez
  • 設定藍芽顯示的名稱

首先,我們先來觀察一下樹莓派的藍芽相關裝置,尤其是藍芽位址,這個藍芽硬體位址跟乙太網路的位址很類似! 我們可以直接這樣看:

 $ hciconfig -a
hci0:   Type: Primary  Bus: UART
        BD Address: B8:27:EB:27:51:76  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN
        RX bytes:1538 acl:0 sco:0 events:98 errors:0
        TX bytes:3550 acl:0 sco:0 commands:98 errors:0
        Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
        Link policy: RSWITCH SNIFF
        Link mode: SLAVE ACCEPT
        Name: 'raspberrypi'
        Class: 0x2c0000
        Service Classes: Rendering, Capturing, Audio
        Device Class: Miscellaneous,
        HCI Version: 4.1 (0x7)  Revision: 0x1fc
        LMP Version: 4.1 (0x7)  Subversion: 0x2209
        Manufacturer: Broadcom Corporation (15)

上面我們可以看到我們樹莓派上面的藍芽裝置名稱為 hci0 ,然後目前的狀態是正在運行中 (UP RUNNING)。如果你發現藍芽沒開啟, 或者是想要關閉藍芽的功能,就可以這樣做看看:

# 關閉藍芽
$ sudo hciconfig hci0 down

# 啟動藍芽
$ sudo hciconfig hci0 up

另外,也能使用 hcitool 這個指令來查看一下樹莓派上面的藍芽裝置的位址與裝置名稱喔:

$ hcitool dev
Devices:
        hci0    B8:27:EB:27:51:76

由於你可能會有很多台樹莓派,如果每一台樹莓派的名稱 (上面顯示 raspberrypi 字樣的地方),那可能會很難判斷這是那一台? 這時,可以透過 bluetoothctl 指令,來進行名稱的修改喔!

# 先看一下自己的名字
 $ bluetoothctl
Agent registered
[bluetooth]# show
Controller B8:27:EB:27:51:76 (public)
        Name: raspberrypi
        Alias: raspberrypi
        Class: 0x002c0000
        Powered: yes
.....

[bluetooth]# system-alias 'rpi-vbird'
Changing rpi-vbird succeeded
[CHG] Controller B8:27:EB:27:51:76 Alias: rpi-vbird

[bluetooth]# show
Controller B8:27:EB:27:51:76 (public)
        Name: raspberrypi
        Alias: rpi-vbird
        Class: 0x002c0000
...

這樣就修改了你的藍芽名稱了!如果需要修改回預設值,在 [bluetooth]# 底下輸入『 reset-alias 』,就可以復原名稱了!

  • 進行藍芽掃描與配對

再來則是需要進行藍芽裝置的掃描與配對~最常使用的藍芽裝置,恐怕就是音響音箱設備了!我們這裡準備一個簡單的藍芽設備, 打開電源之後,在 bluetoothctl 裡面這樣做,應該能抓到相關的設備名稱:

 $ bluetoothctl
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller B8:27:EB:27:51:76 Discovering: yes
[NEW] Device 36:F0:F0:BB:78:7B Kingone K88
[CHG] Device 36:F0:F0:BB:78:7B RSSI: -55

# 開始配對這個設備
[bluetooth]# pair 36:F0:F0:BB:78:7B
Attempting to pair with 36:F0:F0:BB:78:7B
[CHG] Device 36:F0:F0:BB:78:7B Connected: yes
[CHG] Device 36:F0:F0:BB:78:7B UUIDs: 00001101-0000-1000-8000-00805f9b34fb
[CHG] Device 36:F0:F0:BB:78:7B UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 36:F0:F0:BB:78:7B UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 36:F0:F0:BB:78:7B UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 36:F0:F0:BB:78:7B ServicesResolved: yes
[CHG] Device 36:F0:F0:BB:78:7B Paired: yes
Pairing successful
[CHG] Device 36:F0:F0:BB:78:7B ServicesResolved: no
[CHG] Device 36:F0:F0:BB:78:7B Connected: no

[bluetooth]# paired-devices
Device 36:F0:F0:BB:78:7B Kingone K88

[bluetooth]# devices
Device 36:F0:F0:BB:78:7B Kingone K88

有的藍芽設備配對時,需要輸入配對碼,但是上面這顆藍芽音響,似乎不用配對碼就可以連線成功!要確定時, 可以使用上述『 paired-devices 』重複確認一下即可!看起來是有連線成功的!不過,藍芽傳輸似乎不是這麼穩定, 所以,設定上面要從藍芽音響傳出來,好像還有點困難啊~

15.5: 當週實做

拿出你的手機,搜尋一下目前的 WIFI 狀態,選擇你剛剛設定的 SSID,並且輸入正確的密碼後, 查詢看看是否有合理的網際網路可用權限!完成之後請呼叫老師,作為一次實習成績。

  • 參考資料 for nmcli
  1. 簡單的使用圖形界面就搞定 wifi AP 功能的文件:
    https://www.tomshardware.com/how-to/raspberry-pi-access-point
  2. 使用 nmcli 作為無線 AP 功能 (非常詳細):
    https://variwiki.com/index.php?title=Wifi_NetworkManager
  3. 查詢 nmcli 的 802-11-wireless-security 相關參數:
    https://developer-old.gnome.org/NetworkManager/stable/settings-802-11-wireless-security.html
  • 參考資料 for hostap
  1. 一份寫的挺好的樹莓派建置 AP 英文文件:
    https://raspberrypi-guide.github.io/networking/create-wireless-access-point
  2. 邊程人的學習筆記:
    https://dotblogs.com.tw/sideprogrammer/2019/02/17/raspberry-pi-set-ap
  3. ufw 達成 NAT 的技術:
    https://gist.github.com/kimus/9315140
  4. askubuntu.com 討論區當中的 ufw 達成 NAT 技術快速解答:
    https://askubuntu.com/questions/1151289/ufw-rules-with-nat-masquerading
  • 更改紀錄
  • 2022/11/20:這一篇其實是為了資傳系進修部 2023 年畢業的同學們提早寫的!為了與 arduino 的 IoT 設備搭配在一起, 得要使用 AP 啊!其實挺有趣的!簡單的使用 NetworkManager,要比另外一種方式來的簡單呢!雖然過程當中,查錯資料, 耗費了兩天的時光才完成這篇...
  • 2022/12/18:不知道要將藍芽放在哪裡,因為篇幅真的不大!所以,只好放在這裡了!

...