2023/09/25

firewalld

在 rockylinux 8 以前,可以不使用firewalld,還是沿用舊的 iptables

# Stop firewalld
systemctl stop firewalld
# disable firewalld
systemctl disable firewalld
# hide firewalld
systemctl mask firewalld

安裝 iptables

dnf -y install iptables iptables-services

systemctl enable iptables
systemctl start iptables
systemctl status --no-pager iptables

在 rockylinux 9 以後,firewalld 成為預設的 firewall

  • firewalld 支援 network/firewall zones,定義 trust level of network connections

  • 同時支援 IPv4, IPv6

  • 支援由 service/applcation 直接建立 firewall rules

如果有圖形介面,可透過 firewall-config 進行 firewall 設定

啟用 firewalld

systemctl enable --now firewalld
systemctl restart firewalld

systemctl status --no-pager firewalld

基本指令

以下是 firewalld 幾個基本常用的指令

# 檢查 firewalld 狀態
firewall-cmd --state

# 設定完成後,要重新載入設定,讓設定永久生效
firewall-cmd --reload

# 查閱設定
firewall-cmd --list-all

# 查閱詳細設定
firewall-cmd --list-rich-rules

# 將設定永久儲存
firewall-cmd --runtime-to-permanent

# 在設定過程中,直接增加rule 並永久儲存
firewall-cmd --permanent [the rest of your command]

zone

firewalld 最重要的是加入了 zone 的概念,以下是內建基本的 zones

zone 說明 example use
drop 不回應任何封包,直接拒絕所有外部連線,只允許內部往外傳送的 packets。 drop incoming connections without reply - only outgoing packets are allowed
block 以 icmp-host-prohibited, icmp6-adm-prohibited 拒絕外部連線 incoming connections are rejected with an icmp-host-prohibited message for IPv4 and icmp6-adm-prohibited for IPv6
public 允許所有外部連線 all incoming connections are allowed
external 有使用 IP 偽裝時,用在外部網路 for use on external networks with masquerading enabled
dmz 給 DMZ 的電腦使用 for computers on your demilitarized zone that are publicly-accessible with limited access to your internal network
work for computers in work areas (nope, I don't get this one either)
home for use in home areas (nope, I don't get this one either)
internal 內部網路使用 for your internal network device access
trusted 允許所有網路連線 all network connections are accepted

如果滿足以下兩個條件中某一個,該 zone 就會是在 active 狀態

  1. zone 被綁定到某一個 network interface

  2. zone 被綁定 source IPs 或 network ranges

一般使用者比較會使用 trusted, home, public 這幾個 zone

zone 的相關指令

# 查詢 default zone
firewall-cmd --get-default-zone

# 查詢 active zones
firewall-cmd --get-active-zones

# 修改 default zone
firewall-cmd --set-default-zone [your-zone]

# 將某個 zone 綁定 network interface
firewall-cmd --zone=[your-zone] --add-interface=[your-network-device]

# 修改 zone 的 network interface
firewall-cmd --zone=[your-zone] --change-interface=[your-network-device]

# 移除 network interface
firewall-cmd --zone=[your-zone] --remove-interface=[your-network-device]

# 新增 zones
firewall-cmd --new-zone=[your-new-zone]
firewall-cmd --get-zones

rule

port

# 查詢
firewall-cmd --list-ports

# add remove
firewall-cmd --zone=public --add-port=9001/tcp
firewall-cmd --zone=public --add-port=20000-20100/tcp

firewall-cmd --zone=public --remove-port=9001/tcp

service

# 查詢可使用的 services
firewall-cmd --get-services

# 查詢目前的 active services
firewall-cmd --list-services

# add/remove
firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --remove-service=http

ip

firewall-cmd --permanent --zone=trusted --add-source=192.168.1.0/24

firewall-cmd --permanent --zone=trusted --remove-source=192.168.1.0/24

rich rule

#單一IP

firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.1.100' reject"
#除了針對特定單一IP外,再針對特別連線port進行設定
firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="3306" accept'
#針對IP範圍
firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' reject"

firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.77.100/32" accept'

在 iptables, firewalld 允許某個 ip 使用 ssh

# iptables
iptables -A INPUT -p tcp -m tcp -s 192.168.1.122 --dport 22 -j ACCEPT

# firewalld
firewall-cmd --zone=trusted --add-source=192.168.1.122 --permanent
firewall-cmd --zone=trusted --add-service=ssh --permanent

# remove
firewall-cmd --zone=trusted --remove-source=192.168.1.122
firewall-cmd --zone=trusted --remove-service ssh

# 儲存設定
firewall-cmd --runtime-to-permanent
firewall-cmd --reload

ICMP rule

# iptables
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -s 192.168.1.136 -j ACCEPT

# "public" zone 的 ICMP 預設是開啟的
# block ICMP in "public" "trusted" zone
firewall-cmd --zone=public --add-icmp-block={echo-request,echo-reply} --permanent
firewall-cmd --zone=trusted --add-icmp-block={echo-request,echo-reply} --permanent

web server ports

# iptables
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

# add service
firewall-cmd --zone=public --add-service=http --add-service=https --permanent

# 移除
firewall-cmd --zone=public --remove-service=http --remove-service=https --permanent

DNS

# iptables
iptables -A INPUT -p udp -m udp -s 192.168.1.0/24 --dport 53 -j ACCEPT

# 
firewall-cmd --zone=trusted --add-service=dns
firewall-cmd --zone=public --add-service=dns

TCP state

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# firewalld 不需要做這個設定

mysql

# iptables
iptables -A INPUT -p tcp -m tcp --dport=3600 -j ACCEPT

# firewalld
firewall-cmd --zone=public --add-service=mysql --permanent

postgresql

# iptables
iptables -A INPUT -p tcp -m tcp --dport 5432 -s 192.168.1.0/24 -j ACCEPT

# firewalld
firewall-cmd --zone=trusted --add-service=postgresql

References

Enabling iptables Firewall - Documentation

firewalld from iptables - Documentation

firewalld for Beginners - Documentation

基本防火牆設定 | 晟鑫科技線上手冊

Firewalld 防火牆 - HackMD

Linux Firewall-cmd 防火牆安裝, 允許/禁止 IP, Port 用法介紹

2023/09/18

OAuth

傳統的 Client-Server 架構裡, Client 要拿取受保護的資源 (Protected Resoruce) 的時候,要向 Server 出示使用者 (Resource Owner) 的帳號密碼才行。如果要讓第三方應用程式也可以使用這些 Resources ,則需要 Resource Owner 把帳號密碼給這個第三方應用程式,這時候會產生以下的問題:

  • 第三方應用程式必須以明碼儲存 Resource Owner 的帳號密碼
  • Server 要支援密碼認證
  • 第三方應用程式會得到完整存取 Protected Resources 的權限,無法限制時效
  • Resource Owner 無法只撤回某一個第三方應用程式的存取權,必須要修改密碼才能撤回。
  • 當某一個第三方應用程式被破解,就會導致使用該密碼的所有資料被破解。

OAuth 解決這些問題的方式,是引入一個認證層 (authorization layer) ,並把 client 跟 resource owner 的角色分開。Client 會先索取存取權,來存取 Resource Owner 擁有的資源,這些資源會放在 Resource Server 上面,並且 Client 會得到一組不同於 Resource Owner 所持有的認證碼,也就是 access token。

角色定義

  • Resource Owner

    可授權別人去存取 Protected Resource。如果這個角色是人類的話,就是指使用者 (end-user)。

  • Resource Server

    存放 Protected Resource 的伺服器,可以根據 Access Token 來接受使用 Protected Resource 的請求。

  • Client

    讓 Resource Owner 授權後,可以去存取 Protected Resource 的應用程式。

  • Authorization Server

    認證 Resource Owner 並獲得 Resource Owner 許可後,核發 Access Token 的伺服器。

+--------+                               +---------------+
|        |--(A)- Authorization Request ->|   Resource    |
|        |                               |     Owner     |
|        |<-(B)-- Authorization Grant ---|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(C)-- Authorization Grant -->| Authorization |
| Client |                               |     Server    |
|        |<-(D)----- Access Token -------|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(E)----- Access Token ------>|    Resource   |
|        |                               |     Server    |
|        |<-(F)--- Protected Resource ---|               |
+--------+                               +---------------+

Refresh Token 流程

+--------+                                           +---------------+
|        |--(A)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(B)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(C)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(D)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(E)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(F)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(G)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(H)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+

Grant Flow

Authorization Code Grant Type Flow

+----------+
| Resource |
|   Owner  |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
  |    |                                         ^      v
 (A)  (C)                                        |      |
  |    |                                         |      |
  ^    v                                         |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)
  • 要向 Authorization Server 先取得 Grant Code 再取得 Access Token。
  • 適合 Confidential Clients ,如部署在 Server 上面的應用程式。
  • 可以核發 Refresh Token。
  • 需要 User-Agent Redirection。

Implicit Grant Type Flow

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier     +---------------+
|         -+----(A)-- & Redirection URI --->|               |
|  User-   |                                | Authorization |
|  Agent  -|----(B)-- User authenticates -->|     Server    |
|          |                                |               |
|          |<---(C)--- Redirection URI ----<|               |
|          |          with Access Token     +---------------+
|          |            in Fragment
|          |                                +---------------+
|          |----(D)--- Redirection URI ---->|   Web-Hosted  |
|          |          without Fragment      |     Client    |
|          |                                |    Resource   |
|     (F)  |<---(E)------- Script ---------<|               |
|          |                                +---------------+
+-|--------+
  |    |
 (A)  (G) Access Token
  |    |
  ^    v
+---------+
|         |
|  Client |
|         |
+---------+
  • Authorization Server 直接向 Client 核發 Access Token (一步)。
  • 適合非常特定的 Public Clients ,例如跑在 Browser 裡面的應用程式。
  • Authorization Server 不必(也無法)驗證 Client 的身份。
  • 禁止核發 Refresh Token。
  • 需要 User-Agent Redirection。
  • 有資料外洩風險。

Resource Owner Password Credentials Grant Type Flow

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     v
     |    Resource Owner
    (A) Password Credentials
     |
     v
+---------+                                  +---------------+
|         |>--(B)---- Resource Owner ------->|               |
|         |         Password Credentials     | Authorization |
| Client  |                                  |     Server    |
|         |<--(C)---- Access Token ---------<|               |
|         |    (w/ Optional Refresh Token)   |               |
+---------+                                  +---------------+
  • Resource Owner 的帳號密碼直接拿來當做 Grant。
  • 適用於 Resource Owner 高度信賴的 Client (像是 OS 內建的)或是官方應用程式。
  • 其他流程不適用時才能用。
  • 可以核發 Refresh Token。
  • 沒有 User-Agent Redirection。

Client Credentials Grant Type Flow

+---------+                                  +---------------+
|         |                                  |               |
|         |>--(A)- Client Authentication --->| Authorization |
| Client  |                                  |     Server    |
|         |<--(B)---- Access Token ---------<|               |
|         |                                  |               |
+---------+                                  +---------------+
  • Client 的帳號與密碼直接用來 Grant
  • 適用於跑在 Server 上面的 Confidential Client
  • 不建議核發 Refresh Token
  • 沒有 User-Agent Redirection

References

OAuth 2.0 筆記 (1) 世界觀

OAuth 2.0 筆記 (4.1) Authorization Code Grant Flow 細節

OAuth 2.0 筆記 (4.2) Implicit Grant Flow 細節

OAuth 2.0 筆記 (4.3) Resource Owner Password Credentials Grant Flow 細節

OAuth 2.0 筆記 (4.4) Client Credentials Grant Flow 細節

各大網站 OAuth 2.0 實作差異 2013

2023/09/11

mDNS DNS-SD

DNS-SD(DNS Service Discovery) 跟 mDNS (multicast DNS) 是不同的 protocol,但可以互相相容。DNS-SD 能透過標準的 DNS 技術,尋找區域網路中,提供某些服務的協定。而 mDNS 是能夠在區域網路中,在不需要 DNS Server 的情況下,就能透過機器名稱,直接查出 IP。

apple 的 Bonjour protocol 就是合併了 mDNS 與 DNS-SD 實作的。

mDNS

可用在沒有 DNS server 的區域網路中,用來作機器 domain name 的 IP 查詢。設備會透過對 224.0.0.251 這個 multicast address,Port 為 5353,進行廣播,mDNS 使用跟 DNS 一樣的封包格式。mDNS 只接受 .local 的網域名稱,可同時運作在一個設備中,跟原本的 DNS 並存。

mDNS 也有為自己命名的功能,在自選了一個 domain name 後,會用記錄類型為 any 的 mDNS 封包查詢是否有同樣的 domain name 的另一台機器,如果沒有,就會設定為自己的 domain name。

DNS-SD

基於 DNS,主要用到三種記錄類型:PTR、SRV、TXT

  • Service Discovery

    設備會先發送一個 PTR 記錄的 multicast 查詢封包,查詢的格式為

    <service>.<transport>.<domain>

    service 是查詢的服務,transport 為傳輸協定: TCP 或 UDP,domain 為查詢網域,在 mDNS 為 .local。查詢後,具有該服務的設備就會回應

    <instance>.<service>.<transport>.<domain>

    ex: 查詢 _easylink._tcp.localEMW3031 Module#500A3F._easylink._tcp.local 回應

    就表示 EMW3031 Module#500A3F 是符合該 service 的 instance

  • 取得 instance 的 domain name 與 port

    當有多個 instance 回應後,選擇某一個 instance,然後需要查詢該 instance 的 domain name 與 port,也就是查詢 SRV 記錄

    _service._proto.name. TTL class SRV priority weight port target.

    priority 和 weight 沒有作用,通常設定為 0

    port 與 target 就分別是 port 與 domain name

    ex:

    EMW3031 Module#500A3F._easylink._tcp.local. 3 IN SRV 0 0 8002 EMW3031 Module#500A3F.local.
  • 更詳細的資訊

    除了 domain name 與 port 以外,還能夠提供更多資訊,就是記錄在 TXT record 中,以 key=value 格式記錄的資訊

    ex:

    MAC=D0:BA:E4:50:0A:3F

CentOS7 avahi

Avahi is a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite.

安裝 avahi

yum install nss-mdns avahi avahi-tools

啟動

systemctl start avahi-daemon

出現錯誤訊息

 dbus_bus_request_name(): Connection ":1.44573" is not allowed to own the service "org.freedesktop.Avahi" due to security policies in the configuration file

要重新啟動 dbus, NetworkManager

systemctl restart dbus.service

# /var/log/messages 會出現錯誤訊息
# (NetworkManager:624): GLib-GIO-CRITICAL **: Error while sending AddMatch () message: 這個連線已關閉
systemctl restart NetworkManager
# 避免 ssh 登入問題
# Failed to activate service 'org.freedesktop.login1': timed out
systemctl restart systemd-logind

再啟動 avahi-demon

systemctl start avahi-daemon

然後就能查詢 LAN 的機器

# avahi-browse -a
+ enp3s0 IPv4 lzstg [6c:62:6d:ce:71:c7]                     Workstation          local
+ enp3s0 IPv4 macmini2                                      Microsoft Windows Network local
+ enp3s0 IPv4 macmini2                                      Apple File Sharing   local
+ enp3s0 IPv4 macmini2                                      Apple Net Assistant  local
+ enp3s0 IPv4 Michael's MacBook Pro                         Microsoft Windows Network local
+ enp3s0 IPv4 Michael's MacBook Pro                         _companion-link._tcp local

也可以直接 ping *.local 的機器

# ping macmini2.local
PING macmini2.local (192.168.1.159) 56(84) bytes of data.
64 bytes from 192.168.1.159 (192.168.1.159): icmp_seq=1 ttl=64 time=0.675 ms
64 bytes from 192.168.1.159 (192.168.1.159): icmp_seq=2 ttl=64 time=0.374 ms

發布 service

avahi-publish-service SERVICE-NAME _APPLICATIONPROTOCOL._TRANPOSRT-PROTOCOL PORT "DESCRIPTION" --sub SUBPROTOCOL

ex:

avahi-publish-service light _coap._udp 5683 “/mylight” --sub
_floor1._sub._coap._udp

發布 service name: light,使用 CoAP protocol,在 UDP 5683 提供服務

該 service 可透過 _coap._udp.local_floor1._sub._coap._udp.local 被發現

References

UWP - mDNS 找尋附近的設備

MDNS/DNS-SD TUTORIAL

使用 mDNS 在區域網中輕鬆發現系統

Bonjour手把手搭建一:mDNS(apple & multicastdns.org)

區域網設備發現之Bonjour協議