2025年7月21日 星期一

Python 學習筆記 : 網頁爬蟲實戰 (十八) 擷取隨機的格言 (上)

前陣子發現 Mapleboard 的 Ubuntu Mate 升版後自動新增了預設的 Guest 帳戶, 因為其權限不足以連線網路, 導致主機掛點網站連埠上. 修復此問題後花了近一個月時間來打理架站與主機安全防護. 這兩天完成後想說應該要讓主機每天早上傳送一個訊息 (Email 或 LINE/Telegram 訊息) 給我, 讓我知道系統仍正常運行中才對. 那要傳甚麼呢? 當然, 傳個 "早安" 是再簡單不過了, 但我想弄點較有意思的, 那就傳個名言或格言吧!

本系列全部測試文章索引參考 :



1. 撰寫格言爬蟲 : 

我找到下面這個免申請帳號與 Key 就能取得格言的網站 : 





它提供一個可隨機傳回格言的 API 網址 : 


在瀏覽器輸入此 API url 會傳回一個 JSON 字串 : 

[ {"q":"Pleasure can be supported by an illusion; but happiness rests upon truth. ","a":"Nicolas Chamfort","h":"<blockquote>&ldquo;Pleasure can be supported by an illusion; but happiness rests upon truth. &rdquo; &mdash; <footer>Nicolas Chamfort</footer></blockquote>"} ]

其中 "q" 鍵為格言本身, "a" 鍵為作者, 我們可以用 requests 來取得格言內容 :

>>> import requests  
>>> url='https://zenquotes.io/api/random'    
>>> res=requests.get(url)    
>>> res   
<Response [200]>

呼叫 Response 物件的 json() 方法將 JSON 字串轉成字典串列 : 

>>> data=res.json()  
>>> type(data)   
<class 'list'>   
>>> len(data)   
1

可見此串列只有一個元素 :

>>> data[0]  
{'q': 'Experience is a comb which nature gives us when we are bald. ', 'a': 'Chinese Proverb', 'h': '<blockquote>&ldquo;Experience is a comb which nature gives us when we are bald. &rdquo; &mdash; <footer>Chinese Proverb</footer></blockquote>'}
>>> data[0]['q']   
'Experience is a comb which nature gives us when we are bald. '
>>> data[0]['a']   
'Chinese Proverb'

這樣便取得格言內容與作者了, 可以將上面程序寫成 get_quote() 函式 :

>>> def get_quote(): 
    url='https://zenquotes.io/api/random'
    try:
        res=requests.get(url, timeout=10)
        data=res.json()
        return data[0]['q'], data[0]['a']  # 成功傳回 (quote, author)
    except Exception as e:
        return None, f'Failed to fetch quote: {e}'   # 失敗傳回 (None, '失敗訊息')
    
呼叫函式 : 

>>> quote, author=get_quote()   
>>> quote   
'You have to keep breaking your heart until it opens.'
>>> author    
'Rumi'


2. 利用 Google Gemini 翻譯格言 : 

但我想要同時顯示其中文翻譯 (中英對照), 格式例如 :

快樂可以靠幻想支撐,
但幸福建立在真理之上。
Pleasure can be supported by an illusion;
but happiness rests upon truth.

—— Nicolas Chamfort

中文翻譯可以利用 Google Gemini 大語言模型搭配合適的提示詞來達成, 這必須先申請 Gemini API Key 與安裝 google-generativeai 套件, 作法參考 :


我已有 Gemini API Key, 先存入變數中 :

>>> gemini_api_key='我的 Gemini API Key'     

然後匯入 google.generativeai 模組並取簡名 genai : 

>>> import google.generativeai as genai  

接著呼叫 configure() 函式並傳入 API Key 來認證金鑰 : 

>>> genai.configure(api_key=gemini_api_key)   

若沒有傳回錯誤訊息那就表示認證成功了,  呼叫 GenerativeModel() 函式並傳入模型名稱來建立模型物件, 考量反應速度我選擇 'gemini-2.0-flash' 模型 : 

>>> model=genai.GenerativeModel('gemini-2.0-flash')    

然後設計提示詞要求模型依照指示執行翻譯任務 : 

>>> prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'   
>>> prompt    
'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:You have to keep breaking your heart until it opens.'

最後呼叫模型物件的 generate_content() 方法來生成翻譯 : 

>>> reply=model.generate_content(prompt)      

回應內容放在回應物件的 text 屬性中 : 

>>> reply.text  
'你必須不斷讓你的心碎裂,直到它敞開。\n'

將上面程序寫成如下之函式 : 

>>> def translate_quote(quote, api_key):
    genai.configure(api_key=api_key)
    model=genai.GenerativeModel('gemini-2.0-flash')
    prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
    try:
        reply=model.generate_content(prompt)
        return reply.text.strip().strip('\"\n ')  # 清除結尾開頭之雙引號跳行與空格

    except Exception as e:
        return f'格言翻譯失敗:{e}'
  
>>> quote_zh_tw=translate_quote(quote, gemini_api_key)   
>>> quote_zh_tw  
'你必須不斷地讓你的心碎裂,直到它敞開。'

這樣就可以將格言之中英文與作者用 f 字串組成輸出訊息了 :

>>> def bilingual_quote(quote, quote_zh_tw, author):
    return f'早安! 今日格言:\n「{quote_zh_tw}」\n{quote}\n—— {author}'   
  
>>> msg=bilingual_quote(quote, quote_zh_tw, author)    
>>> msg    
'早安! 今日格言:\n「你必須不斷地讓你的心破碎,直到它真正敞開。」\nYou have to keep breaking your heart until it opens.\n—— Rumi'

以上測試的完整程式碼如下 :

# dailly_quote.py
import requests
import google.generativeai as genai

def get_quote():
    url='https://zenquotes.io/api/random'
    try:
        res=requests.get(url, timeout=10)
        data=res.json()
        return data[0]['q'], data[0]['a']  # 成功傳回 (quote, author)
    except Exception as e:
        return None, f'Failed to fetch quote: {e}'  # 失敗傳回 (None, '失敗訊息')
    
def translate_quote(quote, api_key):
    genai.configure(api_key=api_key)
    model=genai.GenerativeModel('gemini-2.0-flash')
    prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
    try:
        reply=model.generate_content(prompt)
        return reply.text.strip().strip('\"\n ')  # 清除結尾開頭之雙引號跳行與空格
    except Exception as e:
        return f'格言翻譯失敗:{e}'
 
def bilingual_quote(quote, quote_zh_tw, author):
    return f'早安! 今日格言:\n「{quote_zh_tw}」\n{quote}\n—— {author}'

# 取得每日格言與其中文翻譯
quote, author=get_quote()
gemini_api_key='我的 Gemini API Key'
quote_zh_tw=translate_quote(quote, gemini_api_key)
msg=bilingual_quote(quote, quote_zh_tw, author)
print(msg)

執行結果如下 :

>>> %Run dailly_quote.py   
早安! 今日格言:
「開始一件事情遠比完成它容易得多。」
It is far easier to start something than it is to finish it.
—— Amelia Earhart 


3. 利用 Google SMTP 郵件伺服器傳送每日格言 : 

使用 Google SMTP 伺服器傳送郵件的方法參考 :


我取其中 smtp_mail_test_2.py 的 send_mail() 添加主旨 Unicode 處理, 改寫上面的 dailly_quote.py 如下 :

# dailly_quote.py
import requests
import google.generativeai as genai
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header  

def get_quote():
    url='https://zenquotes.io/api/random'
    try:
        res=requests.get(url, timeout=10)
        data=res.json()
        return data[0]['q'], data[0]['a']  # 成功傳回 (quote, author)
    except Exception as e:
        return None, f'Failed to fetch quote: {e}'  # 失敗傳回 (None, '失敗訊息')
    
def translate_quote(quote, api_key):
    genai.configure(api_key=api_key)
    model=genai.GenerativeModel('gemini-2.0-flash')
    prompt=f'請將以下英文翻譯為繁體中文, 只要翻譯一次即可:{quote}'
    try:
        reply=model.generate_content(prompt)
        return reply.text.strip().strip('\"\n ')  # 清除結尾開頭之雙引號跳行與空格
    except Exception as e:
        return f'格言翻譯失敗:{e}'
 
def bilingual_quote(quote, quote_zh_tw, author):
    return f'早安! 今日格言:\n「{quote_zh_tw}」\n{quote}\n—— {author}'

def send_mail(account, password, subject, from_addr, to_addr, cc_addr=None, body=''):
    if cc_addr is None:
        cc_addr=[]  # 預設空串列
    # 登入 Google SMTP 伺服器
    smtp=smtplib.SMTP('smtp.gmail.com', 587)
    smtp.ehlo()
    smtp.starttls()  # 啟動 TLS 安全傳輸
    smtp.login(account, password)  # 登入 Google SMTP 伺服器
    # 建立郵件內容
    content=MIMEMultipart()
    content['Subject']=Header(subject, 'utf-8') 
    content['From']=from_addr
    content['To']=', '.join(to_addr)
    content['Cc']=', '.join(cc_addr)
    # 添加郵件正文
    content.attach(MIMEText(body, 'plain', 'utf-8'))
    # 合併收件人和副本收件人
    all_recipients=to_addr + cc_addr
    status=smtp.sendmail(from_addr, all_recipients, content.as_string())
    if status == {}:
        print('郵件傳送成功!')
    else:
        print('郵件傳送失敗!')
    smtp.quit()

# 取得每日格言與其中文翻譯
quote, author=get_quote()
gemini_api_key='我的 Gemini API Key'
quote_zh_tw=translate_quote(quote, gemini_api_key)
msg=bilingual_quote(quote, quote_zh_tw, author)
# 用 Google SMTP 伺服器傳送信件
account='mygmail@gmail.com'     # Gmail 帳號
password='azfkqbjbftodjucd'         # Google 應用程式密碼 (這是樣本)
subject='今日格言'                        # 主旨
from_addr='mygmail@gmail.com'   # 寄件人
to_addr=['myhinet@ms5.hinet.net']  # 收件人
cc_addr=[]                            # 副本
body=msg                            # 信件內容
send_mail(account, password, subject, from_addr, to_addr, cc_addr, body)

結果如下 : 

 >>> %Run dailly_quote.py   
郵件傳送成功!



2025年7月20日 星期日

2025 年第 29 周記事

上週五早上因載菁菁去工作室, 到公司時已近九點, 機車停車棚剩下一個車位, 但是有人很機車, 車頭就是要朝外, 這樣照後鏡就會阻礙我的機車停進去, 因為背包會卡住他們的照後鏡, 我只好把我的機車抬一下, 沒想到竟然閃到腰, 結果痛了一個禮拜, 每天睡前貼痠痛藥布, 直到昨天整整一周才比較自然些. 整個車棚幾十台機車, 就是有兩台喜歡頭朝外, 圖的就是下班時不用倒退, 直接跨上走人, 但卻沒想到他們的照後鏡會造成別人的困擾. 其實之前就曾經因為背包被卡過, 所以我平常都是敬而遠之, 這次是因為只剩頭朝外那台旁邊有空位才招來禍事. 

本周持續優化 Mapleboard 的安全防護措施, 到今天終於完善了, 也從 AI 學到非常多 Linux 的管理技巧, 未來不管想學甚麼都可以用這種 AI 協作模式來提速. 接下來便是好好把 Flask 學完, 應用在 Web app 開發上. 另外就是要開始 PyTorch 的學習了, 我的 NLP 就卡在這一關. 

由於薇帕颱風尾周末掃過東南部, 帶來豐沛雨水與災害, 我這兩天的芭樂套袋工作也是剛好避開了下下停停的雨, 週六下午套了 90 顆; 今日套了 60 顆, 合計 150 顆. 邊套邉採也摘了 20 多顆帶來高雄送人 (同事 & 警衛 & 二姨丈). 

延宕了好幾周的鄉下老家修繕+整理計畫下周要開始動手了 :
  • 鄉下車庫屋頂透明罩翻新 (需買一個 Silicon 槍)
  • 洗衣機三通管接管
  • 舊豬舍外牆電源開關防雨盒製作
  • 清理冰箱
  • 清理車庫雜物
  • 清理庫房雜物
要做的事情還很多, 一個一個來吧!

Mapleboard MP510-50 測試 (三十四) : 更改 SSH 通訊埠之埠號

今天繼續修改 Fail2ban 設定來強化主機安全性, 本篇測試旨在更改 Mapleboard SSH 通訊埠埠號, 由預設的 22 改為 2222. 

本系列全部的測試紀錄參考 :
將 SSH 埠號從預設的 22 改為其他非標準埠 (例如 2222), 這種做法稱為 "透過模糊化提升安全性", 可以在一定程度上減少自動掃描與暴力破解的攻擊次數, 優點如下 : 
  • 降低被掃描頻率 :
    大多數惡意機器人與腳本程式通常會集中攻擊 22 埠, 改用非標準埠例如 2222 埠會使主機避開大部分低階攻擊. 
  • 減少 Fail2Ban 負擔 :
    因為暴力破解頻率降低了, fail2ban 就不用頻繁寫入封鎖紀錄, 可節省系統資源. 
但修改 SSH 埠號無法完全防止入侵. 有心的攻擊者會利用通訊埠掃描工具 (例如 nmap) 輕易地找出主機所使用的 SSH 埠. 

修改 SSH 通訊埠號程序如下 :


1. 修改 SSH 設定檔 : 

先用 cat 檢視 SSH 的設定檔 /etc/ssh/sshd_config : 

tony1966@LX2438:~$ cat /etc/ssh/sshd_config    

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

#Port 22       #  在底下新增 Port 2222 明確指定 SSH 使用 2222 埠
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server

用 nano 編輯 sshd 設定檔 : 

sudo nano /etc/ssh/sshd_config  

tony1966@LX2438:~$ sudo nano /etc/ssh/sshd_config   
[sudo] tony1966 的密碼: 

在底下 #Port 22 新增 Port 2222 明確指定 SSH 使用 2222 埠 (或直接將 22 改成 2222) : 




按 Ctrl+O 存檔後按 Ctrl+X 跳出 nano 即可. 


2. UFW 防火牆開啟 2222 埠 : 

這步非常重要必須先下, 如果先刪除 22 埠那 SSH 就連不進來了, 指令如下 :

sudo ufw allow 2222/tcp    

tony1966@LX2438:~$ sudo ufw allow 2222/tcp  
已添加規則
已添加規則 (v6)

檢視防火牆狀態 :

tony1966@LX2438:~$ sudo ufw status verbose   
狀態: 啓用
日誌: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
新建設定檔案: skip

至                          動作          來自
-                          --          --
22/tcp                     ALLOW IN    Anywhere                  
80/tcp                     ALLOW IN    Anywhere                  
443/tcp                    ALLOW IN    Anywhere                  
2222/tcp                   ALLOW IN    Anywhere                  
22/tcp (v6)                ALLOW IN    Anywhere (v6)             
80/tcp (v6)                ALLOW IN    Anywhere (v6)             
443/tcp (v6)               ALLOW IN    Anywhere (v6)     
2222/tcp (v6)              ALLOW IN    Anywhere (v6)    

可見 2222 埠已開啟.


3. 暫時允許 22/2222 雙埠重新啟動 SSH 服務 : 

在確保新埠 2222 能順利連入之前, 不要馬上移除原本的 22 port 規則 : 

sudo systemctl restart ssh   

tony1966@LX2438:~$ sudo systemctl restart ssh   


4. 用 Putty 測試 2222 埠是否可連線 : 

開啟 Putty, 將 port 設為 2222 開啟連線, 確認可順利登入 : 


 


用 HTmail 帳密可以登入, 就可以封鎖 22 埠了.


5. UFW 防火牆移除 22 埠 : 

用下列指令關閉 22 埠 :

sudo ufw delete allow 22/tcp   

tony1966@LX2438:~$ sudo ufw delete allow 22/tcp  
已刪除規則
已刪除規則 (v6)

檢視防火牆狀態 :

tony1966@LX2438:~$ sudo ufw status verbose   
狀態: 啓用
日誌: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
新建設定檔案: skip

至                          動作          來自
-                          --          --
80/tcp                     ALLOW IN    Anywhere                  
443/tcp                    ALLOW IN    Anywhere                  
2222/tcp                   ALLOW IN    Anywhere                  
80/tcp (v6)                ALLOW IN    Anywhere (v6)             
443/tcp (v6)               ALLOW IN    Anywhere (v6)     
2222/tcp (v6)              ALLOW IN    Anywhere (v6)    

可見 22 埠已經被封鎖. 再次重啟 ssh 服務 : 

tony1966@LX2438:~$ sudo systemctl restart ssh   


6. 更新 Fail2Ban 的 SSH jail 設定 : 

用下列指令編輯 Fail2ban 的設定檔 jail.local, 修改 sshd 的監控規則 : 

sudo nano /etc/fail2ban/jail.local   

tony1966@LX2438:~$ sudo nano /etc/fail2ban/jail.local   

將其中的 port 參數從原先的 ssh 或 22 改為 2222 : 

port = 2222

另外在 sshd 區段末尾添加下面這一行 : 

action = %(action_mwl)s  

這是 fail2ban 預設模板中一個內建的動作縮寫, 此動作有如下作用 : 
  • 封鎖企圖暴力破解的 IP (保護 2222 埠)
  • 記錄封鎖事件到 /var/log/fail2ban.log 日誌檔
  • 發送郵件通知 (需在 DEFAULT 區段配置 mta 和 destemail)
然後在 [sshd] 區段底下 (註 : 錯誤, 是上面, 見底下補充說明) 新增一個 [DEFAULT] 區段, 設定寄件者與收件者 :

[DEFAULT]
mta = postfix
destemail = yhhuang1966@gmail.com
sender = fail2ban@tony1966.cc




按 Ctrl+O 存檔後按 Ctrl+X 跳出 nano. 

然後重啟 Fail2Ban :

sudo systemctl restart fail2ban   

tony1966@LX2438:~$ sudo systemctl restart fail2ban   


7. 檢查目前 SSH Daemon 是否使用 2222 : 

用下列指令檢查目前 SSH Daemon 是否使用 2222 :

sudo ss -tnlp | grep sshd    

tony1966@LX2438:~$  sudo ss -tnlp | grep sshd   
LISTEN 0      128          0.0.0.0:2222      0.0.0.0:*    users:(("sshd",pid=604384,fd=3))                              
LISTEN 0      128             [::]:2222         [::]:*    users:(("sshd",pid=604384,fd=4))      

此處 0.0.0.0:2222 表示監聽所有 IPv4 網卡上的 2222 埠; 而 [::]:2222 則是監聽所有 IPv6 網卡上的 2222 埠, 這樣就確認了以上操作已成功地將 SSH 監聽埠號改為 2222, 且 SSH 服務也已正常啟動並在預期的 IPv4 和 IPv6 埠號 2222 上監聽. 


2025-07-25 補充 :

上周末更新完 jail.local 後一直沒有收到監控資訊的 Email, 今天進入系統檢查, 發現 sshd 監控根本沒有載入 :

tony1966@LX2438:~$ sudo fail2ban-client status sshd   
2025-07-25 00:26:04,215 fail2ban [678576]: 
ERROR NOK: ('sshd',) Sorry but the jail 'sshd' does not exist 
tony1966@LX2438:~$ sudo fail2ban-client status     
Status |- Number of jail: 4 - Jail list: nginx-404, nginx-badbots, nginx-noscript, recidive

詢問 AI 才知原來 jail.local 中 DEFAULT 區塊應該放在 sshd 最前面才對 : 

[DEFAULT]
mta = postfix
destemail = yhhuang1966@gmail.com
sender = yhhuang1966@gmail.com

[sshd]
enabled = true
port = 2222
logpath = /var/log/auth.log
maxretry = 5
bantime = 1h
findtime = 10m
action = %(action_mwl)s

但即使順序弄對了還是不行. AI 建議將 action = %(action_mwl)s 改成 action = %(action_mw)s 或 action = %(action_)s 試試看, 測試結果如下 :

action = %(action_mwl)s  --> NG
action = %(action_mw)s  --> NG
action = %(action_)s  --> OK (5 個規則都有載入)

這個 action 用來設定預設的封鎖與通知方式, 來自於 /etc/fail2ban/action.d/ 目錄中定義的行為模板, 它們的差異在於是否寄信與包含 log 摘要內容, 這三種設定的差異如下 :

action = %(action_mwl)s  : 封鎖 IP + 寄信通知 + 包含違規 log 摘要
action = %(action_mw)s : 封鎖 IP + 寄信通知, 但不含違規 log 摘要內容
action = %(action_)s : 只封鎖 IP 不會寄信通知

我需要寄信通知, 前兩個設定會 NG 的原因可能是缺少 /etc/fail2ban/action.d/postfix-whois.conf 這個檔案, 我用 nano 建立了此檔 : 

tony1966@LX2438:~$ sudo nano /etc/fail2ban/action.d/postfix-whois.conf 

輸入如下內容 : 

[Definition]
actionstart =
actionstop =
actioncheck =
actionban = postfix[name=%(__name__)s, dest="%(destemail)s", sender="%(sender)s"]
actionunban =

重啟 Fail2ban 還是不行, AI 認為可能 Postfix 安裝或設定有問題, 需要重新安裝, 但建議將 jail.local 裡面的 mta 直接改為 sendmail 最快, 我使用 action = %(action_mw)s 搭配 mta=sendmail 果然就可以了, 完整的 jail.local 如下  :

tony1966@LX2438:~$ cat /etc/fail2ban/jail.local   
[DEFAULT]
mta = postfix
destemail = yhhuang1966@gmail.com
sender = yhhuang1966@gmail.com

[sshd]
enabled = true
port = 2222
logpath = /var/log/auth.log
maxretry = 5
bantime = 1h
findtime = 10m
action = %(action_)s

[nginx-404]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 10m
bantime = 1h

[nginx-badbots]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 1
findtime = 1d
bantime = 1d

[nginx-noscript]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 10m
bantime = 1h

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 86400       ; 1 天
findtime = 1d
maxretry = 5

檢視 Fail2ban 狀態 :

tony1966@LX2438:~$ sudo fail2ban-client status   
[sudo] tony1966 的密碼: 
Status
|- Number of jail: 5
`- Jail list: nginx-404, nginx-badbots, nginx-noscript, recidive, sshd

tony1966@LX2438:~$ sudo fail2ban-client status sshd   
[sudo] tony1966 的密碼: 
Status for the jail: sshd
|- Filter
|  |- Currently failed: 5
|  |- Total failed: 135
|  `- File list: /var/log/auth.log
`- Actions
   |- Currently banned: 0
   |- Total banned: 7
   `- Banned IP list:


可見 5 個監控規則都順利載入運行中, 而且馬上收到封鎖 IP 的 Email : 

Hi,

The IP 45.135.232.92 has just been banned by Fail2Ban after
5 attempts against sshd.


Here is more information about 45.135.232.92 :

% This is the RIPE Database query service.
% The objects are in RPSL format.
%
% The RIPE Database is subject to Terms and Conditions.
% See https://docs.db.ripe.net/terms-conditions.html

% Note: this output has been filtered.
%       To receive output for a database update, use the "-B" flag.

% Information related to '45.135.232.0 - 45.135.232.255'

% Abuse contact for '45.135.232.0 - 45.135.232.255' is 'mail@proton66.ru'

inetnum:        45.135.232.0 - 45.135.232.255
netname:        RU-PROTON66
country:        RU
org:            ORG-PL533-RIPE
admin-c:        PL14453-RIPE
tech-c:         PL14453-RIPE
status:         ASSIGNED PA
mnt-by:         IP-RIPE
created:        2023-03-31T20:14:04Z
last-modified:  2023-03-31T20:14:07Z
source:         RIPE

organisation:   ORG-PL533-RIPE
org-name:       Proton66 LLC
org-type:       OTHER
address:        pr-kt Iskrovskiy, d. 21YU, kv. 218
address:        193230 Saint Petersburg
address:        Russia
abuse-c:        PL14453-RIPE
mnt-ref:        IP-RIPE
mnt-by:         IP-RIPE
created:        2023-03-31T20:10:41Z
last-modified:  2023-03-31T20:10:41Z
source:         RIPE # Filtered

role:           Proton66 LLC
nic-hdl:        PL14453-RIPE
address:        pr-kt Iskrovskiy, d. 21YU, kv. 218
address:        193230 Saint Petersburg
address:        Russia
abuse-mailbox:  mail@proton66.ru
phone:          +7 999 5285271
mnt-by:         IP-RIPE
created:        2023-03-31T20:09:34Z
last-modified:  2023-03-31T20:10:30Z
source:         RIPE # Filtered

% Information related to '45.135.232.0/24AS198953'

route:          45.135.232.0/24
origin:         AS198953
mnt-by:         IP-RIPE
created:        2023-04-14T19:15:16Z
last-modified:  2023-04-14T19:15:16Z
source:         RIPE

% This query was served by the RIPE Database Query Service version 1.117 (DEXTER)

Regards,

Fail2Ban

大部分都是來自中國與俄羅斯的, 真是駭客之邦啊!

Mapleboard MP510-50 測試 (三十三) : Postfix 郵件伺服器安全設定

在前一篇測試中已安裝好郵件工具包 Postfix 與 mailutils 並成功地透過 Google SMTP 郵件伺服器傳送 Email, 本篇則是要針對 Postfix 郵件伺服器加強安全防護. 

本系列全部的測試紀錄參考 :


Postfix 作為一個郵件傳輸代理 (MTA), 雖然設計上注重安全, 但若設定不當或未及時更新版本 (postfix 與相關之 libsasl2-2, ca-certificates 等套件), 仍然存在潛在的資安風險, 例如遭受暴力破解後, 攻擊者可能利用 Postfix 發送垃圾郵件, 這會導致 Postfix 伺服器被 Google 列入黑名單而無法正常寄信. 其次, 預設的 Postfix 日誌 (/var/log/mail.log) 包含敏感資訊 (如發信人/收信人地址), 若伺服器被入侵, 則日誌可能被用來收集個資. 

由於我的 Mapleboard 的 Postfix 僅作為 SMTP 客戶端 (運行 smtp 進程), 僅連接到 Google 的 SMTP 伺服器 (smtp.gmail.com:587) 寄信, 不開放 25, 587 或 465 埠接受外部連線 (即不運行 smtpd 進程來處理外部請求, 只寄信不收信), 因此不需要在 jail.local 中設定監控規則, 因為 Fail2Ban 的 Postfix 監控是針對外部攻擊, 如果只收信就不會有外部 IP 觸發日誌中的異常行為, Fail2Ban 的 Postfix 監控規則就沒有實際作用, 但是必須進行下列安全防護檢視與設定.  


1. 保護 Google 帳戶憑證 (密碼檔 /etc/postfix/sasl_passwd 權限設為 600) :

此項在前一篇測試中已完成設定, 可用 stat 指令直接查詢權限的數字表示 :

tony1966@LX2438:~$ stat -c "%a" /etc/postfix/sasl_passwd   
600
tony1966@LX2438:~$ stat -c "%a" /etc/postfix/sasl_passwd.db 
600


2. 確保 TLS 加密 (smtp_use_tls = yes 和 smtp_tls_security_level = encrypt)

在前一篇測試中已在 Postfix 設定檔 /etc/postfix/main.cf 中添加如下設定 : 

# Gmail SMTP settings
relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_use_tls = yes   

其中包含了 smtp_use_tls = yes 設定. 而 smtp_tls_security_level 參數在 /etc/postfix/main.cf 設定檔中已經預設為 smtp_tls_security_level=may, 此設定會讓 Postfix 嘗試使用 TLS 與遠端 SMTP 伺服器 (例如 smtp.gmail.com:587) 建立加密連線, 但如果遠端伺服器不支援 TLS, 則會退回到未加密連線. 如果 Google SMTP 伺服器因某種原因無法使用 TLS (雖然這極少發生), 連線可能以明文傳輸, 會導致認證憑證 (例如應用程式密碼) 或郵件內容暴露, 因此設為 may不夠安全. 

用 nano 編輯 /etc/postfix/main.cf 設定檔, 將 smtp_tls_security_level 參數改為 encrypt : 

smtp_tls_security_level=encrypt  

tony1966@LX2438:~$ sudo nano /etc/postfix/main.cf  
[sudo] tony1966 的密碼: 




按 Ctrl+O 存檔後按 Ctrl+X 跳出 nano 即可. 


3. 配置防火牆 (禁止內連 25, 587, 465 埠但允許外連 587 埠) : 

由於我僅使用 Postfix 作為 SMTP 客戶端連接到 Google 的 SMTP 伺服器 (smtp.gmail.com:587) 寄信, 並不運行 Postfix 的 smtpd 進程 (意即不接受外部 SMTP 連線收信), 因此不需要開放 25, 587 或 465 埠的內連流量, 保持這些埠在關閉狀態可以避免不必要的網路攻擊 (例如暴力破解或垃圾郵件中繼等). 

用 sudo ufw status verbose 指令檢視 UFW 防火牆設定 :

tony1966@LX2438:~$ sudo ufw status verbose  
狀態: 啓用
日誌: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
新建設定檔案: skip

至                          動作          來自
-                          --          --
22/tcp                     ALLOW IN    Anywhere                  
80/tcp                     ALLOW IN    Anywhere                  
443/tcp                    ALLOW IN    Anywhere                  
22/tcp (v6)                ALLOW IN    Anywhere (v6)             
80/tcp (v6)                ALLOW IN    Anywhere (v6)             
443/tcp (v6)               ALLOW IN    Anywhere (v6)             

可見目前的 ufw 規則中並未允許 25, 587 或 465 埠的內連流量, 其中 Default: deny (incoming), allow (outgoing) 表示防火牆預設阻止全部內連流量 (除了下方所列之手動開啟埠號外), 且允許全部外連流量, 所以 Postfix 要連線 Google SMTP 伺服器 (587 埠) 沒有問題. 但如果為了管理上強調 須保持 587 埠可外連, 也可以用下列指令做顯式設定 :  

sudo ufw allow out to any port 587


4. 定期更新 Postfix 和相關套件 : 

在 Postfix + mailutils 透過 Google SMTP 寄信的應用場景下須定期更新的 Postfix 相關套件如下 :
  • postfix : 負責處理郵件寄送的核心郵件傳輸代理 (MTA) 
  • mailutils : 提供 mail 指令用來在命令列寄送郵件
  • libsasl2-2 : SASL 相關套件 (用於 Google SMTP 認證), 提供認證框架
  • libsasl2-modules : SASL 相關套件 (用於 Google SMTP 認證), SASL 認證模組
  • ca-certificates : 提供 CA 憑證以驗證 Google SMTP 伺服器的 TLS 連線
可以使用下列指令進行版本更新 :

sudo apt update   (更新套件清單)
sudo apt upgrade   (套件升版)


5. 保護日誌文件 (/var/log/mail.log 權限設為 640) : 

可用 stat 指令查詢日誌檔權限, 它會直接傳回權限的數字表示 :

tony1966@LX2438:~$ stat -c "%a" /var/log/mail.log   
640 

2025年7月17日 星期四

Mapleboard MP510-50 測試 (三十二) : 安裝 postfix 與 mailutils

在前一篇測試中已完成入侵偵測與監控軟體 Fail2ban 的設定, 但如果要知道封鎖了多少入侵企圖與封鎖了那些 IP 必須登入系統用指令去查看, 如果能將監控資訊寄送的 Email 就方便多了. 但是在 jail.local 監控規則中納入 email 參數之前必須先讓主機具備寄送 email 功能. 

在 Linux 系統中寄送 email 通常使用 postfix + mailutils 組合 :
  • Postfix :
    一個郵件傳送代理 (MTA) 軟體, 負責在底層處理郵件的實際寄送任務, 將系統或程式產生的郵件發送到收件人的郵件伺服器 (Postfix 支援送收信功能, 但它的基本功能是寄信, 若要收信還需搭配安裝郵件投遞代理 軟體 MDA 才行). 
  • mailutils :
    一組郵件工具函式庫, 提供多種郵件相關指令 (例如寄信的 mail 指令), 讓使用者能在命令列環境中用 shell 指令撰寫與送收郵件. 它本身不會直接傳送郵件, 而是呼叫系統中的 MTA (例如 Postfix) 來完成郵件寄送. 
總之兩者就是上層 (mailutils) 與下層 (postfix) 的協作關係.  

但我在安裝 mailutils 時卻碰壁, 原因是以前安裝 Anydesk 時指定了錯誤的 CPU 核心架構 (Mapleboard 是 arm64, 但卻錯誤地新增了 amd64 架構),  事後沒有清除掉, 導致更新套件時找錯套件庫, 無法下載 arm64 架構所需套件, 本篇旨在紀錄我透過 AI 協助排除障礙後順利安裝這兩個軟體的過程. 

本系列全部的測試紀錄參考 :



1. 更新套件清單 :   

此指令用來更新系統的套件資料庫 : 

tony1966@LX2438:~$ sudo apt update   
下載:1 https://packages.microsoft.com/repos/code stable InRelease [3,590 B]
下載:2 https://packages.microsoft.com/repos/code stable/main amd64 Packages [20.5 kB]
下載:3 https://packages.microsoft.com/repos/code stable/main arm64 Packages [20.5 kB]
下載:4 https://packages.microsoft.com/repos/code stable/main armhf Packages [20.6 kB]
下載:5 http://ports.ubuntu.com/ubuntu-ports jammy InRelease [270 kB]
下載:6 http://ports.ubuntu.com/ubuntu-ports jammy-updates InRelease [128 kB]
下載:7 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease [129 kB]
下載:8 http://ports.ubuntu.com/ubuntu-ports jammy-backports InRelease [127 kB]
略過:9 http://ports.ubuntu.com/ubuntu-ports jammy/main amd64 Packages
下載:10 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 Packages [1,369 kB]
下載:11 http://ports.ubuntu.com/ubuntu-ports jammy/main armhf Packages [1,323 kB]
下載:12 http://ports.ubuntu.com/ubuntu-ports jammy/main Translation-en [510 kB]
下載:13 http://ports.ubuntu.com/ubuntu-ports jammy/main Translation-zh_TW [58.4 kB]
下載:14 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 c-n-f Metadata [29.8 kB]
下載:15 http://ports.ubuntu.com/ubuntu-ports jammy/restricted arm64 Packages [19.6 kB]
下載:16 http://ports.ubuntu.com/ubuntu-ports jammy/restricted armhf Packages [10.9 kB]
略過:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted amd64 Packages
下載:18 http://ports.ubuntu.com/ubuntu-ports jammy/restricted Translation-zh_TW [708 B]
下載:19 http://ports.ubuntu.com/ubuntu-ports jammy/restricted Translation-en [18.6 kB]
下載:20 http://ports.ubuntu.com/ubuntu-ports jammy/restricted arm64 c-n-f Metadata [372 B]
下載:21 http://ports.ubuntu.com/ubuntu-ports jammy/universe arm64 Packages [13.9 MB]
下載:22 http://ports.ubuntu.com/ubuntu-ports jammy/universe armhf Packages [13.5 MB]                                                                 
略過:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe amd64 Packages                                                                           
下載:24 http://ports.ubuntu.com/ubuntu-ports jammy/universe Translation-en [5,652 kB]                                                                
下載:25 http://ports.ubuntu.com/ubuntu-ports jammy/universe Translation-zh_TW [42.0 kB]                                                              
下載:26 http://ports.ubuntu.com/ubuntu-ports jammy/universe arm64 c-n-f Metadata [277 kB]                                                            
下載:27 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse arm64 Packages [184 kB]                                                                
略過:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse amd64 Packages                                                                         
下載:29 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse armhf Packages [164 kB]                                                                
下載:30 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse Translation-zh_TW [3,960 B]                                                            
下載:31 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse Translation-en [112 kB]                                                                
下載:32 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse arm64 c-n-f Metadata [7,064 B]                                                         
略過:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main amd64 Packages                                                                       
下載:34 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 Packages [2,526 kB]                                                            
下載:35 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main armhf Packages [1,181 kB]                                                            
下載:36 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main Translation-en [437 kB]                                                              
下載:37 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 c-n-f Metadata [18.2 kB]                                                       
下載:38 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted arm64 Packages [3,585 kB]                                                      
略過:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted amd64 Packages                                                                 
下載:40 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted armhf Packages [18.5 kB]                                                       
下載:41 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted Translation-en [725 kB]                                                        
下載:42 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted arm64 c-n-f Metadata [524 B]                                                   
下載:43 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe armhf Packages [951 kB]                                                          
下載:44 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe arm64 Packages [1,215 kB]                                                        
略過:45 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe amd64 Packages                                                                   
下載:46 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe Translation-en [302 kB]                                                          
下載:47 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe arm64 c-n-f Metadata [25.6 kB]                                                   
下載:48 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse armhf Packages [6,180 B]                                                       
下載:49 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse arm64 Packages [40.4 kB]                                                       
略過:50 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse amd64 Packages                                                                 
下載:51 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse Translation-en [14.2 kB]                                                       
下載:52 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse arm64 c-n-f Metadata [320 B]                                                   
略過:9 http://ports.ubuntu.com/ubuntu-ports jammy/main amd64 Packages                                                                                
略過:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/main amd64 Packages                                                                      
下載:54 http://ports.ubuntu.com/ubuntu-ports jammy-security/main armhf Packages [956 kB]                                                             
下載:55 http://ports.ubuntu.com/ubuntu-ports jammy-security/main arm64 Packages [2,255 kB]                                                           
下載:56 http://ports.ubuntu.com/ubuntu-ports jammy-security/main Translation-en [370 kB]                                                             
下載:57 http://ports.ubuntu.com/ubuntu-ports jammy-security/main arm64 c-n-f Metadata [13.2 kB]                                                      
下載:58 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted arm64 Packages [3,314 kB]                                                     
略過:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted amd64 Packages                                                                
下載:60 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted armhf Packages [16.3 kB]                                                      
下載:61 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted Translation-en [677 kB]                                                       
下載:62 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted arm64 c-n-f Metadata [472 B]                                                  
下載:63 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe arm64 Packages [987 kB]                                                         
下載:64 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe armhf Packages [730 kB]                                                         
略過:65 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe amd64 Packages                                                                  
下載:66 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe Translation-en [214 kB]                                                         
下載:67 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe arm64 c-n-f Metadata [19.0 kB]                                                  
略過:68 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse amd64 Packages                                                                
下載:69 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse armhf Packages [2,864 B]                                                      
下載:70 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse arm64 Packages [22.8 kB]                                                      
下載:71 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse Translation-en [8,908 B]                                                      
下載:72 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse arm64 c-n-f Metadata [280 B]                                                  
略過:73 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main amd64 Packages                                                                     
下載:74 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main arm64 Packages [68.5 kB]                                                           
下載:75 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main armhf Packages [68.4 kB]                                                           
下載:76 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main Translation-en [11.4 kB]                                                           
下載:77 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main arm64 c-n-f Metadata [392 B]                                                       
下載:78 http://ports.ubuntu.com/ubuntu-ports jammy-backports/restricted arm64 c-n-f Metadata [116 B]                                                 
下載:79 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe arm64 Packages [28.4 kB]                                                       
略過:80 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe amd64 Packages                                                                 
下載:81 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe armhf Packages [28.4 kB]                                                       
下載:82 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe Translation-en [16.5 kB]                                                       
下載:83 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe arm64 c-n-f Metadata [600 B]                                                   
下載:84 http://ports.ubuntu.com/ubuntu-ports jammy-backports/multiverse arm64 c-n-f Metadata [116 B]                                                 
略過:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted amd64 Packages                                                                         
略過:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe amd64 Packages                                                                           
略過:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse amd64 Packages                                                                         
略過:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main amd64 Packages                                                                       
略過:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted amd64 Packages                                                                 
略過:45 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe amd64 Packages                                                                   
略過:50 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse amd64 Packages                                                                 
略過:9 http://ports.ubuntu.com/ubuntu-ports jammy/main amd64 Packages                                                                                
略過:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/main amd64 Packages                                                                      
略過:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted amd64 Packages                                                                
略過:65 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe amd64 Packages                                                                  
略過:68 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse amd64 Packages                                                                
略過:73 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main amd64 Packages                                                                     
略過:80 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe amd64 Packages                                                                 
略過:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted amd64 Packages                                                                         
略過:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe amd64 Packages                                                                           
略過:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse amd64 Packages                                                                         
略過:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main amd64 Packages                                                                       
略過:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted amd64 Packages                                                                 
略過:45 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe amd64 Packages                                                                   
略過:50 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse amd64 Packages                                                                 
略過:9 http://ports.ubuntu.com/ubuntu-ports jammy/main amd64 Packages                                                                                
略過:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/main amd64 Packages                                                                      
略過:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted amd64 Packages                                                                
略過:65 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe amd64 Packages                                                                  
略過:68 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse amd64 Packages                                                                
略過:73 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main amd64 Packages                                                                     
略過:80 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe amd64 Packages                                                                 
略過:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted amd64 Packages                                                                         
略過:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe amd64 Packages                                                                           
略過:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse amd64 Packages                                                                         
略過:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main amd64 Packages                                                                       
略過:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted amd64 Packages                                                                 
略過:45 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe amd64 Packages                                                                   
略過:50 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse amd64 Packages                                                                 
略過:9 http://ports.ubuntu.com/ubuntu-ports jammy/main amd64 Packages                                                                                
略過:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/main amd64 Packages                                                                      
略過:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted amd64 Packages                                                                
略過:65 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe amd64 Packages                                                                  
略過:68 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse amd64 Packages                                                                
略過:73 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main amd64 Packages                                                                     
略過:80 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe amd64 Packages                                                                 
略過:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted amd64 Packages                                                                         
略過:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe amd64 Packages                                                                           
略過:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse amd64 Packages                                                                         
略過:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main amd64 Packages                                                                       
略過:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted amd64 Packages                                                                 
略過:45 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe amd64 Packages                                                                   
略過:50 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse amd64 Packages                                                                 
錯誤:9 http://ports.ubuntu.com/ubuntu-ports jammy/main amd64 Packages                                                                                
  404  Not Found [IP: 91.189.91.104 80]
略過:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/main amd64 Packages                                                                      
略過:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted amd64 Packages                                                                
略過:65 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe amd64 Packages                                                                  
略過:68 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse amd64 Packages                                                                
略過:73 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main amd64 Packages                                                                     
略過:80 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe amd64 Packages                                                                 
略過:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted amd64 Packages                                                                         
略過:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe amd64 Packages                                                                           
略過:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse amd64 Packages                                                                         
錯誤:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main amd64 Packages                                                                       
  404  Not Found [IP: 91.189.91.104 80]
略過:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted amd64 Packages                                                                 
略過:45 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe amd64 Packages                                                                   
略過:50 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse amd64 Packages                                                                 
錯誤:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/main amd64 Packages                                                                      
  404  Not Found [IP: 91.189.91.104 80]
略過:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted amd64 Packages                                                                
略過:65 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe amd64 Packages                                                                  
略過:68 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse amd64 Packages                                                                
錯誤:73 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main amd64 Packages                                                                     
  404  Not Found [IP: 91.189.91.104 80]
略過:80 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe amd64 Packages                                                                 
取得 58.8 MB 用了 15s (3,808 kB/s)                                                                                                                   
正在讀取套件清單... 完成
E: 無法取得 http://ports.ubuntu.com/ubuntu-ports/dists/jammy/main/binary-amd64/Packages,404  Not Found [IP: 91.189.91.104 80]
E: 無法取得 http://ports.ubuntu.com/ubuntu-ports/dists/jammy-updates/main/binary-amd64/Packages,404  Not Found [IP: 91.189.91.104 80]
E: 無法取得 http://ports.ubuntu.com/ubuntu-ports/dists/jammy-security/main/binary-amd64/Packages,404  Not Found [IP: 91.189.91.104 80]
E: 無法取得 http://ports.ubuntu.com/ubuntu-ports/dists/jammy-backports/main/binary-amd64/Packages,404  Not Found [IP: 91.189.91.104 80]
E: Some index files failed to download. They have been ignored, or old ones used instead.

注意上面的 404 部分, 這是安裝 mailutils 時無法下載套件而失敗的原因. 


2. 安裝 postfix 與 mailutils :   

這兩個軟體可以一起用 apt install 安裝 : 

tony1966@LX2438:~$ sudo apt install postfix mailutils    
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
下列的額外套件將被安裝:
  gsasl-common guile-3.0-libs libgsasl7 libmailutils8 libmysqlclient21 libntlm0 libpq5 mailutils-common mysql-common
建議套件:
  mailutils-mh mailutils-doc procmail postfix-mysql postfix-pgsql postfix-ldap postfix-pcre postfix-lmdb postfix-sqlite sasl2-bin | dovecot-common
  resolvconf postfix-cdb postfix-mta-sts-resolver postfix-doc
下列【新】套件將會被安裝:
  gsasl-common guile-3.0-libs libgsasl7 libmailutils8 libmysqlclient21 libntlm0 libpq5 mailutils mailutils-common mysql-common postfix
升級 0 個,新安裝 11 個,移除 0 個,有 10 個未被升級。
需要下載 11.4 MB 的套件檔。
此操作完成之後,會多佔用 69.9 MB 的磁碟空間。
是否繼續進行 [Y/n]? [Y/n] Y
下載:1 http://ports.ubuntu.com jammy-security/main arm64 postfix arm64 3.6.4-1ubuntu1.3 [1,237 kB]
下載:2 http://ports.ubuntu.com jammy/universe arm64 gsasl-common all 1.10.0-5 [59.8 kB]
下載:3 http://ports.ubuntu.com jammy/universe arm64 guile-3.0-libs arm64 3.0.7-1 [7,539 kB]
下載:4 http://ports.ubuntu.com jammy/universe arm64 libntlm0 arm64 1.6-4 [74.0 kB]
下載:5 http://ports.ubuntu.com jammy/universe arm64 libgsasl7 arm64 1.10.0-5 [69.9 kB]
下載:6 http://ports.ubuntu.com jammy/universe arm64 mailutils-common all 1:3.14-1 [382 kB]
下載:7 http://ports.ubuntu.com jammy/main arm64 mysql-common all 5.8+1.0.8 [7,212 B]
略過:8 http://ports.ubuntu.com jammy-security/main arm64 libmysqlclient21 arm64 8.0.37-0ubuntu0.22.04.3
略過:9 http://ports.ubuntu.com jammy-security/main arm64 libpq5 arm64 14.12-0ubuntu0.22.04.1
下載:10 http://ports.ubuntu.com jammy/universe arm64 libmailutils8 arm64 1:3.14-1 [490 kB]
下載:11 http://ports.ubuntu.com jammy/universe arm64 mailutils arm64 1:3.14-1 [123 kB]
錯誤:8 http://ports.ubuntu.com jammy-security/main arm64 libmysqlclient21 arm64 8.0.37-0ubuntu0.22.04.3
  404  Not Found [IP: 2620:2d:4000:1::19 80]
錯誤:9 http://ports.ubuntu.com jammy-security/main arm64 libpq5 arm64 14.12-0ubuntu0.22.04.1                                                         
  404  Not Found [IP: 2620:2d:4000:1::19 80]
取得 9,981 kB 用了 6s (1,591 kB/s)                                                                                                                   
E: 無法取得 http://ports.ubuntu.com/pool/main/m/mysql-8.0/libmysqlclient21_8.0.37-0ubuntu0.22.04.3_arm64.deb,404  Not Found [IP: 2620:2d:4000:1::19 80]
E: 無法取得 http://ports.ubuntu.com/pool/main/p/postgresql-14/libpq5_14.12-0ubuntu0.22.04.1_arm64.deb,404  Not Found [IP: 2620:2d:4000:1::19 80]
E: 有部份套件檔無法取得,試著執行 apt-get update 或者試著加上 --fix-missing 選項?

安裝過程顯示 postfix 有被安裝, 途中會跳出設定視窗要求選擇選擇郵件系統類型與輸入系統郵件名稱 (也可以之後用 sudo dpkg-reconfigure postfix 指令進行完整設定) : 
  • 郵件系統類型 : 要選擇 "Internet Site"
  • 系統郵件名稱 : 輸入主機名稱或網域, 例如 tony1966.cc
先按 Tab 鍵移動熱點到 "確定" 鈕時按 Enter : 
 



點選 Internet Site 按 Tab 鍵移動熱點到 "確定" 鈕時按 Enter : 




在 System name 框內輸入主機域名 tony1966.cc, 按 Tab 鍵移動熱點到 "確定" 鈕時按 Enter : 




但是另一個工具包 mailutils 卻因為有部份套件檔無法取得而沒有安裝, 也就是出現 404 錯誤的部分, 具體而言是缺了 libmysqlclient21 與 libpq5 這兩個套件. 

我依照提示使用 sudo apt install postfix mailutils --fix-missing 指令安裝結果還是一樣不行. 詢問 ChatGPT 原因, 它叫我檢視 /etc/apt/sources.list 內容 : 

tony1966@LX2438:~$ cat /etc/apt/sources.list   
deb http://ports.ubuntu.com/ jammy main restricted universe multiverse
# deb-src http://ports.ubuntu.com/ jammy main restricted universe multiverse
deb http://ports.ubuntu.com/ jammy-security main restricted universe multiverse
# deb-src http://ports.ubuntu.com/ jammy-security main restricted universe multiverse
deb http://ports.ubuntu.com/ jammy-updates main restricted universe multiverse
# deb-src http://ports.ubuntu.com/ jammy-updates main restricted universe multiverse
deb http://ports.ubuntu.com/ jammy-backports main restricted universe multiverse
# deb-src http://ports.ubuntu.com/ jammy-backports main restricted universe multiverse

AI 建議在 http://ports.ubuntu.com/ 後面添加 ubuntu-ports 子目錄, 因為 ARM 架構的官方軟體庫都存放在 ubuntu-ports 路徑下, 於是我用 nano 將它改成 : 

tony1966@LX2438:~$ cat /etc/apt/sources.list 
deb http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse

但再次下載安裝還是不行. 

於是我改問 perplexity, 它跟 ChatGPT 一樣也是叫我更新清單重新安裝 : 

tony1966@LX2438:~$ sudo apt clean   
tony1966@LX2438:~$ sudo rm -rf /var/lib/apt/lists/*   
tony1966@LX2438:~$ sudo apt update  

同樣無效, 但是審視我貼上去的 sources.list 覺得路徑完整沒問題, 是正確的 Ubuntu 22.04 ARM64 官方 ports 軟體庫, 但要求我確認系統架構和平台資訊, 因為它懷疑有版本不合或架構誤判可能 (這真的厲害, 有聯想思考能力) : 

"你的系統更新出現大量 404 Not Found 錯誤,是因為你的 /etc/apt/sources.list 指向的官方 Ubuntu 伺服器對 amd64 架構的套件路徑不存在,但你的系統主架構是 arm64。APT 嘗試下載 amd64 架構的套件導致失敗。"

Perplexity 要求我下三個指令回報給它判斷 : 

tony1966@LX2438:~$ dpkg --print-architecture   
arm64
tony1966@LX2438:~$ dpkg --print-foreign-architectures
armhf
amd64
tony1966@LX2438:~$ uname -m   
aarch64

第一個指令是顯示當前系統的架構類型, 回應 arm64 表示 CPU 是 64 位元的 ARM 架構 (若顯示 amd64 表示 64 位元的 x86 架構; i386 表示 32 位元的 x86 架構); 第二個指令用來顯示目前系統中已註冊的外部架構 (foreign architectures), 這些外部架構可以用下列指令添加 :

sudo dpkg --add-architecture amd64  

第三個指令 uname -m 用來顯示系統的硬體架構類型, aarch64 表示 CPU 為 64 位元的 ARM 架構, 與 arm64 意思一樣. Perplexity 根據此三指令之回應研判問題就是出在 amd64 這個外部架構, 只要移除 amd64 架構應該就可以解決此問題 (至於 armhf 則無妨可保留) : 

"你的系統可能之前加入了 amd64 架構(可用 dpkg --print-foreign-architectures 觀看),APT 嘗試同步 amd64,找不到對應檔案就報 404。移除系統不需要且不存在相應套件來源的 amd64 架構,可以解決 apt 更新時出現的大量 404 錯誤,自然也能讓系統找到 mailutils 等套件並安裝成功。"

用下列指令刪除 amd64 架構 :

tony1966@LX2438:~$ sudo dpkg --remove-architecture amd64   
tony1966@LX2438:~$ dpkg --print-foreign-architectures   
armhf

這樣再次更新套件清單就不會出現 404 錯誤了 :

tony1966@LX2438:~$ sudo apt clean   
tony1966@LX2438:~$ sudo rm -rf /var/lib/apt/lists/*   
tony1966@LX2438:~$ sudo apt update 
下載:1 https://packages.microsoft.com/repos/code stable InRelease [3,590 B]
下載:2 http://ports.ubuntu.com/ubuntu-ports jammy InRelease [270 kB]                  
下載:3 https://packages.microsoft.com/repos/code stable/main amd64 Packages [20.5 kB]
下載:4 https://packages.microsoft.com/repos/code stable/main arm64 Packages [20.5 kB]
下載:5 https://packages.microsoft.com/repos/code stable/main armhf Packages [20.6 kB]
下載:6 http://ports.ubuntu.com/ubuntu-ports jammy-updates InRelease [128 kB]                
下載:7 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease [129 kB]
下載:8 http://ports.ubuntu.com/ubuntu-ports jammy-backports InRelease [127 kB]
下載:9 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 Packages [1,369 kB]
下載:10 http://ports.ubuntu.com/ubuntu-ports jammy/main armhf Packages [1,323 kB]
下載:11 http://ports.ubuntu.com/ubuntu-ports jammy/main Translation-en [510 kB]
下載:12 http://ports.ubuntu.com/ubuntu-ports jammy/main Translation-zh_TW [58.4 kB]
下載:13 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 c-n-f Metadata [29.8 kB]
下載:14 http://ports.ubuntu.com/ubuntu-ports jammy/restricted armhf Packages [10.9 kB]
下載:15 http://ports.ubuntu.com/ubuntu-ports jammy/restricted arm64 Packages [19.6 kB]
下載:16 http://ports.ubuntu.com/ubuntu-ports jammy/restricted Translation-zh_TW [708 B]
下載:17 http://ports.ubuntu.com/ubuntu-ports jammy/restricted Translation-en [18.6 kB]
下載:18 http://ports.ubuntu.com/ubuntu-ports jammy/restricted arm64 c-n-f Metadata [372 B]
下載:19 http://ports.ubuntu.com/ubuntu-ports jammy/universe arm64 Packages [13.9 MB]
下載:20 http://ports.ubuntu.com/ubuntu-ports jammy/universe armhf Packages [13.5 MB]                                                                 
下載:21 http://ports.ubuntu.com/ubuntu-ports jammy/universe Translation-en [5,652 kB]                                                                
下載:22 http://ports.ubuntu.com/ubuntu-ports jammy/universe Translation-zh_TW [42.0 kB]                                                              
下載:23 http://ports.ubuntu.com/ubuntu-ports jammy/universe arm64 c-n-f Metadata [277 kB]                                                            
下載:24 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse arm64 Packages [184 kB]                                                                
下載:25 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse armhf Packages [164 kB]                                                                
下載:26 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse Translation-en [112 kB]                                                                
下載:27 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse Translation-zh_TW [3,960 B]                                                            
下載:28 http://ports.ubuntu.com/ubuntu-ports jammy/multiverse arm64 c-n-f Metadata [7,064 B]                                                         
下載:29 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 Packages [2,526 kB]                                                            
下載:30 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main armhf Packages [1,181 kB]                                                            
下載:31 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main Translation-en [437 kB]                                                              
下載:32 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 c-n-f Metadata [18.2 kB]                                                       
下載:33 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted armhf Packages [18.5 kB]                                                       
下載:34 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted arm64 Packages [3,585 kB]                                                      
下載:35 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted Translation-en [725 kB]                                                        
下載:36 http://ports.ubuntu.com/ubuntu-ports jammy-updates/restricted arm64 c-n-f Metadata [524 B]                                                   
下載:37 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe arm64 Packages [1,215 kB]                                                        
下載:38 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe armhf Packages [951 kB]                                                          
下載:39 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe Translation-en [302 kB]                                                          
下載:40 http://ports.ubuntu.com/ubuntu-ports jammy-updates/universe arm64 c-n-f Metadata [25.6 kB]                                                   
下載:41 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse arm64 Packages [40.4 kB]                                                       
下載:42 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse armhf Packages [6,180 B]                                                       
下載:43 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse Translation-en [14.2 kB]                                                       
下載:44 http://ports.ubuntu.com/ubuntu-ports jammy-updates/multiverse arm64 c-n-f Metadata [320 B]                                                   
下載:45 http://ports.ubuntu.com/ubuntu-ports jammy-security/main arm64 Packages [2,255 kB]                                                           
下載:46 http://ports.ubuntu.com/ubuntu-ports jammy-security/main armhf Packages [956 kB]                                                             
下載:47 http://ports.ubuntu.com/ubuntu-ports jammy-security/main Translation-en [370 kB]                                                             
下載:48 http://ports.ubuntu.com/ubuntu-ports jammy-security/main arm64 c-n-f Metadata [13.2 kB]                                                      
下載:49 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted arm64 Packages [3,314 kB]                                                     
下載:50 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted armhf Packages [16.3 kB]                                                      
下載:51 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted Translation-en [677 kB]                                                       
下載:52 http://ports.ubuntu.com/ubuntu-ports jammy-security/restricted arm64 c-n-f Metadata [472 B]                                                  
下載:53 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe armhf Packages [730 kB]                                                         
下載:54 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe arm64 Packages [987 kB]                                                         
下載:55 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe Translation-en [214 kB]                                                         
下載:56 http://ports.ubuntu.com/ubuntu-ports jammy-security/universe arm64 c-n-f Metadata [19.0 kB]                                                  
下載:57 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse armhf Packages [2,864 B]                                                      
下載:58 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse arm64 Packages [22.8 kB]                                                      
下載:59 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse Translation-en [8,908 B]                                                      
下載:60 http://ports.ubuntu.com/ubuntu-ports jammy-security/multiverse arm64 c-n-f Metadata [280 B]                                                  
下載:61 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main armhf Packages [68.4 kB]                                                           
下載:62 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main arm64 Packages [68.5 kB]                                                           
下載:63 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main Translation-en [11.4 kB]                                                           
下載:64 http://ports.ubuntu.com/ubuntu-ports jammy-backports/main arm64 c-n-f Metadata [392 B]                                                       
下載:65 http://ports.ubuntu.com/ubuntu-ports jammy-backports/restricted arm64 c-n-f Metadata [116 B]                                                 
下載:66 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe arm64 Packages [28.4 kB]                                                       
下載:67 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe armhf Packages [28.4 kB]                                                       
下載:68 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe Translation-en [16.5 kB]                                                       
下載:69 http://ports.ubuntu.com/ubuntu-ports jammy-backports/universe arm64 c-n-f Metadata [600 B]                                                   
下載:70 http://ports.ubuntu.com/ubuntu-ports jammy-backports/multiverse arm64 c-n-f Metadata [116 B]                                                 
取得 58.8 MB 用了 22s (2,643 kB/s)                                                                                                                   
正在讀取套件清單... 完成
正在重建相依關係... 完成
正在讀取狀態資料... 完成  
可升級 375 個套件。執行 apt list --upgradable 檢視

再次安裝 mailutils 就可順利下載套件且安裝成功 :

tony1966@LX2438:~$ sudo apt install mailutils    
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
以下套件為自動安裝,並且已經無用:
  libcap2:armhf libsystemd0:armhf
使用 'sudo apt autoremove' 將之移除。
下列的額外套件將被安裝:
  libmailutils8 libmysqlclient21 libpq5
建議套件:
  mailutils-mh mailutils-doc
下列【新】套件將會被安裝:
  libmailutils8 libmysqlclient21 libpq5 mailutils
升級 0 個,新安裝 4 個,移除 0 個,有 375 個未被升級。
需要下載 2,072 kB 的套件檔。
此操作完成之後,會多佔用 9,897 kB 的磁碟空間。
是否繼續進行 [Y/n]? [Y/n] y
下載:1 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 libmysqlclient21 arm64 8.0.42-0ubuntu0.22.04.2 [1,312 kB]
下載:2 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 libpq5 arm64 14.18-0ubuntu0.22.04.1 [147 kB]
下載:3 http://ports.ubuntu.com/ubuntu-ports jammy/universe arm64 libmailutils8 arm64 1:3.14-1 [490 kB]
下載:4 http://ports.ubuntu.com/ubuntu-ports jammy/universe arm64 mailutils arm64 1:3.14-1 [123 kB]
取得 2,072 kB 用了 3s (611 kB/s)   
選取了原先未選的套件 libmysqlclient21:arm64。
(讀取資料庫 ... 目前共安裝了 290367 個檔案和目錄。)
正在準備解包 .../libmysqlclient21_8.0.42-0ubuntu0.22.04.2_arm64.deb……
解開 libmysqlclient21:arm64 (8.0.42-0ubuntu0.22.04.2) 中...
選取了原先未選的套件 libpq5:arm64。
正在準備解包 .../libpq5_14.18-0ubuntu0.22.04.1_arm64.deb……
解開 libpq5:arm64 (14.18-0ubuntu0.22.04.1) 中...
選取了原先未選的套件 libmailutils8:arm64。
正在準備解包 .../libmailutils8_1%3a3.14-1_arm64.deb……
解開 libmailutils8:arm64 (1:3.14-1) 中...
選取了原先未選的套件 mailutils。
正在準備解包 .../mailutils_1%3a3.14-1_arm64.deb……
解開 mailutils (1:3.14-1) 中...
設定 libmysqlclient21:arm64 (8.0.42-0ubuntu0.22.04.2) ...
設定 libpq5:arm64 (14.18-0ubuntu0.22.04.1) ...
設定 libmailutils8:arm64 (1:3.14-1) ...
設定 mailutils (1:3.14-1) ...
update-alternatives: 在自動模式下以 /usr/bin/frm.mailutils 來提供 /usr/bin/frm (frm)
update-alternatives: 在自動模式下以 /usr/bin/from.mailutils 來提供 /usr/bin/from (from)
update-alternatives: 在自動模式下以 /usr/bin/messages.mailutils 來提供 /usr/bin/messages (messages)
update-alternatives: 在自動模式下以 /usr/bin/movemail.mailutils 來提供 /usr/bin/movemail (movemail)
update-alternatives: 在自動模式下以 /usr/bin/readmsg.mailutils 來提供 /usr/bin/readmsg (readmsg)
update-alternatives: 在自動模式下以 /usr/bin/dotlock.mailutils 來提供 /usr/bin/dotlock (dotlock)
update-alternatives: 在自動模式下以 /usr/bin/mail.mailutils 來提供 /usr/bin/mailx (mailx)
執行 man-db (2.10.2-1) 的觸發程式……
執行 libc-bin (2.35-0ubuntu3.8) 的觸發程式……

這樣 postfix 與 mailutils 都已安裝完成. 可以用下列指令檢視 :

tony1966@LX2438:~$ dpkg -l | grep mailutils  
ii  libmailutils8:arm64                      1:3.14-1                                arm64        GNU Mail abstraction library
ii  mailutils                                1:3.14-1                                arm64        GNU mailutils utilities for handling mail
ii  mailutils-common                         1:3.14-1                                all          common files for GNU mailutils
tony1966@LX2438:~$ dpkg -l | grep postfix  
ii  postfix                                  3.6.4-1ubuntu1.3                        arm64        High-performance mail transport agent

有輸出表示已安裝, 可用下列指令查詢其安裝路徑 :

tony1966@LX2438:~$ which postfix  
/usr/sbin/postfix
tony1966@LX2438:~$ which mail  
/usr/bin/mail

檢視 Postfix 的系統服務狀態 :

tony1966@LX2438:~$ systemctl status postfix  
● postfix.service - Postfix Mail Transport Agent
     Loaded: loaded (/lib/systemd/system/postfix.service; enabled; vendor preset: enabled)
     Active: active (exited) since Thu 2025-07-17 10:49:52 CST; 10h ago
       Docs: man:postfix(1)
   Main PID: 487837 (code=exited, status=0/SUCCESS)
        CPU: 5ms

可見 Postfix 服務正在運行 (active), 但其主進程已經結束 (exit), 表示此服務在啟動後會立即退出, 這對 Postfix 而言應該是正常的, 因為 Postfix 主要是作為一個郵件傳輸代理 (Mail Transport Agent), 它可能在啟動時完成一些初始化任務後就會退出, 但它仍然在背景中運行, 其功能是否正常要透過發送測試郵件來驗證. 


3. 安裝認證用套件 :    

上面安裝好 postfix 與 mailutils 後其實還無法使用 mailtils 的 mail 程式傳送信件給 Gmail 信箱, 還需要安裝三個工具包才行, 指令如下 : 

sudo apt install libsasl2-2 libsasl2-modules  ca-certificates    

其中 libsasl2-2 與 libsasl2-modules 用於 Gmail 的 SASL 認證; ca-certificates 用於確保 SSL/TLS 連線正常. 可以用 dpkg 指令先查詢是否已安裝過這三個工具包 : 

tony1966@LX2438:~$ dpkg -l | grep libsasl2-2   
ii  libsasl2-2:arm64                         2.1.27+dfsg2-3ubuntu1.2                 arm64        Cyrus SASL - authentication abstraction library
tony1966@LX2438:~$ dpkg -l | grep ca-certificates    
ii  ca-certificates                          20240203~22.04.1                        all          Common CA certificates
tony1966@LX2438:~$ dpkg -l | grep libsasl2-modules   
ii  libsasl2-modules:arm64                   2.1.27+dfsg2-3ubuntu1.2                 arm64        Cyrus SASL - pluggable authentication modules
ii  libsasl2-modules-db:arm64                2.1.27+dfsg2-3ubuntu1.2                 arm64        Cyrus SASL - pluggable authentication modules (DB)
ii  libsasl2-modules-gssapi-mit:arm64        2.1.27+dfsg2-3ubuntu1.2                 arm64        Cyrus SASL - pluggable authentication modules (GSSAPI)

三個套件都顯示 ii, 表示套件都已安裝且狀態正常. 下列指令可以一次顯示這三個套件的狀態與版本編號 :

tony1966@LX2438:~$ dpkg -l libsasl2-2 ca-certificates libsasl2-modules   
要求=U:未知/I:安裝/R:刪除/P:清除/H:保留
| 狀態=N:未安裝/I:已安裝/C:設定檔/U:已解開/F:半設定/H:半安裝/W:待觸發/T:未觸發
|/ 錯誤?=(無)/R:須重新安裝(狀態,錯誤:大寫=有問題)
||/ 名稱                   版本                    硬體平台     簡介
+++-======================-=======================-============-===============================================
ii  ca-certificates        20240203~22.04.1        all          Common CA certificates
ii  libsasl2-2:arm64       2.1.27+dfsg2-3ubuntu1.2 arm64        Cyrus SASL - authentication abstraction library
ii  libsasl2-modules:arm64 2.1.27+dfsg2-3ubuntu1.2 arm64        Cyrus SASL - pluggable authentication modules


4. 更新 Postfix 設定檔 :   

傳送信件到 Gmail 信箱需要更改 Postfix 的設定檔, 使用 Gmail 的 SMTP 伺服器作為中繼 (relay) 來寄信, 這樣 Mapleboard 才會被視為可被信任的 SMTP 發信主機. 

tony1966@LX2438:~$ cat /etc/postfix/main.cf   
# See /usr/share/postfix/main.cf.dist for a commented, more complete version

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 3.6 on
# fresh installs.
compatibility_level = 3.6

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_security_level=may

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = LX2438
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = tony1966.cc, LX2438, localhost.localdomain, localhost
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

用 nano 編輯 Postfix 設定檔 :

tony1966@LX2438:~$ sudo nano /etc/postfix/main.cf   
[sudo] tony1966 的密碼: 

在最底下添加下列 Gmail SMTP 設定資訊 : 

# Gmail SMTP settings
relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_use_tls = yes

設定值說明如下 :
  • relayhost : 指定 Gmail 的 SMTP 伺服器和埠 (587 埠用於 TLS)
  • smtp_sasl_auth_enable : yes 啟用 SASL 認證
  • smtp_sasl_password_maps : 指向儲存 Gmail 帳戶憑證的文件 (密碼檔)
  • smtp_use_tls : yes 啟用 TLS 加密
按 Ctrl+O 存檔後按 Ctrl+X 跳出 nano. 


5. 建立 Gmail 帳戶憑證密碼檔 :   

在上一步驟中的 Postfix 設定檔裡有一個 smtp_sasl_password_maps 參數用來設定 Gmail 帳戶憑證密碼檔, 裡面需要指定一個 Google 應用程式密碼, 此密碼可在登入 Google 帳號後, 點選 "安全性/ 應用程式密碼" 或直接點下列超連結去建立一組密碼 :


在下方 "應用程式名稱" 框內輸入可辨識的名稱, 按右下角的 "建立" 鈕 : 




將產生的密碼複製下來 : 




用 nano 編輯密碼檔 /etc/postfix/sasl_passwd : 

tony1966@LX2438:~$ sudo nano /etc/postfix/sasl_passwd    
[sudo] tony1966 的密碼: 

輸入下列設定值, 其中 "your-email" 填入 Google 帳號, "應用程式密碼" 填入上面所建立之密碼, 注意, Google 生成之密碼中間有空格, 必須去除後再填入, 總共 16 字元 : 

[smtp.gmail.com]:587 your-email@gmail.com:應用程式密碼

按 Ctrl+O 存檔後按 Ctrl+X 跳出 nano.  

接下來用 postmap 指令轉換密碼檔, postmap 是 Postfix 的一個工具, 用來將純文字的密碼檔 etc/postfix/sasl_passwd 轉換成 Postfix 可以高效讀取的資料庫檔 (has 格式檔)  /etc/postfix/sasl_passwd.db :

tony1966@LX2438:~$ sudo postmap /etc/postfix/sasl_passwd   
[sudo] tony1966 的密碼: 
postmap: warning: /etc/postfix/main.cf, line 50: overriding earlier entry: relayhost=

然後用 chmod 指令更改 sasl_passwd 與 sasl_passwd.db 這兩個檔的權限為僅擁有者 (owner) 可讀寫, 群組與其他使用者無此權限 (600), 這是為了防止密碼洩漏, 避免被用來發送垃圾郵件或盜用帳號 :

tony1966@LX2438:~$ sudo chmod 600 /etc/postfix/sasl_passwd 
tony1966@LX2438:~$ sudo chmod 600 /etc/postfix/sasl_passwd.db  

最後重啟 Postfix 服務 : 

tony1966@LX2438:~$ sudo systemctl restart postfix   

這樣就可以用 mail 指令來寄信了 : 

tony1966@LX2438:~$ echo "這是測試信件" | mail -s "測試主旨" mygmail@gmail.com   

這時去 Gmail 信箱就可以收到這封測試信了 :




可以用下列指令查閱郵件日誌檔最近寄信狀況 :

tony1966@LX2438:~$ sudo tail -f /var/log/mail.log  
[sudo] tony1966 的密碼: 
Jul 18 16:56:44 LX2438 postfix/smtp[579367]: 7E40EC53B8: to=<yhhuang1966@gmail.com>, relay=smtp.gmail.com[2404:6800:4008:c03::6d]:587, delay=552, delays=549/0.3/1.5/1.2, dsn=2.0.0, status=sent (250 2.0.0 OK  1752829004 d9443c01a7336-23e3b60eac6sm9025115ad.53 - gsmtp)
Jul 18 16:56:44 LX2438 postfix/qmgr[579313]: 7E40EC53B8: removed

"status=sent" 表示信件已成功送出. 

以上測試我先在 Mapleboard 上安裝 mailutils 與 postfix 工具包, 更新 Postfix 設定檔後以 mail 程式透過 Google SMTP 郵件伺服器 (smtp.gmail.com) 經過應用程式密碼認證傳送郵件到任何 Email 信箱, 實際的寄件主機並不是我的伺服器, 而是透過 Google 的 SMTP 郵件伺服器作為 relay server 寄出信件. 

因為我只需要寄信不須收信 (毋須打開 ufw 的 25, 465 或 587 埠), 因此最適合採用這種透過 relay server 的 "client 模式" 寄信方式, 而且 Google SMTP 預設會簽 DKIM, 加 SPF, 以及處理 TLS 加密等, 這些措施都增強了郵件的安全性與可信度, 因此透過它寄信送達率高. 

如果想讓 Mapleboard 收信, 那就比較麻煩些, 必須進行下列處置 : 
  • 打開 ufw 的 25 埠 (或 SMTPS 的 465 埠, Submission 的 587 埠)
  • 到 Namecheap 新增 mail.tony1966.cc A 紀錄並調整 DNS 的 SPF, DKIM, MX 記錄
  • 解決 IP 是否在黑名單, Reverse DNS 等問題
  • 安裝支援 IMAP/POP3 協議的 Dovecot
  • 設定 SSL 憑證 (可用 Let's Encrypt)
這似乎不好辦也不需要, 所以就先記著吧.