自從去年臨時換成MikroTik路由器後,功耗和效能都非常滿意,臺灣代理商送來時就有預設的Firewall Rules,完全沒有問題,唯一的不滿就是註解在網路介面看到時是亂碼,詢問代理商說要用 WinBox v3 Windows 版本才能正常顯示註解。WinBox v3還有另一個問題,在高解析度螢幕上文字非常小。
我在家使用的主力是 mac 和 Linux,我也不喜歡使用 WinBox,能夠使用瀏覽器才方便。
雖然沒有太多時間去研究,但基本上所有的路由器都可以匯出文字,所以找Gemini討論。首先,Gemini教我如何匯出,開啟 Terminal,輸入
export file=my_config接下來會在 Files 看到 my_config.rsc ,這是純文字的指令,其中會有Big5中文編碼後的註解
add action=accept chain=input comment="\B6\B6\A7\C7\A6\EC\B8m\A5\B2\B6\B7\A9T\
\A9w--> \B6\B6\A7\C70 (\A9\F1\A6\E6\A6\A8\A5\\\B5n\A4J\AB\E1\AA\BAIP)" \
dst-port=21,22,23,8291 protocol=tcp src-address-list=login-ok
轉換成UTF-8應該是以下這樣,利用新版WinBox貼上註解後也證實如此。
add action=accept chain=input comment="\E9\A0\86\E5\BA\8F\E4\BD\8D\E7\BD\AE\E5\BF\85\E9\A0\88\E5\9B\BA\E5\AE\9A\2D\2D\3E\20\E9\A0\86\E5\BA\8F\30\20\20\28\E6\94\BE\E8\A1\8C\E6\88\90\E5\8A\9F\E7\99\BB\E5\85\A5\E5\BE\8C\E7\9A\84\49\50\29" \
dst-port=21,22,23,8291 protocol=tcp src-address-list=login-ok
在 MikroTik 的 .rsc 檔案中,當字串包含非 ASCII 字元(如中文)時,它會用 \XX 的格式來表示。其中註解文字應為:順序位置必須固定--> 順序0 (放行成功登入後的IP)
所以我們要做的事情就是把這個檔案編碼改為UTF-8, 存檔後刪除原有設定,再重新匯入設定檔。
/import file-name=my_config_utf8.rsc verbose=yes所以在與雙子座多輪對話後,寫出一支轉換 my_config.rsc 變為 my_config_utf8.rsc 的程式,這程式還會列出修改的中文字, 對於不敢直接覆蓋原檔案,可手動修改註解。
import re
import os
def big5_hex_to_utf8_hex(mt_str):
"""將 MikroTik 的 Big5 混合編碼轉換為 UTF-8 的 Hex 轉義格式"""
# 移除斷行連接符號
cleaned_str = re.sub(r'\\\s*[\r\n]+\s*', '', mt_str)
result_bytes = bytearray()
i = 0
while i < len(cleaned_str):
if cleaned_str[i] == '\\':
if i + 1 < len(cleaned_str) and cleaned_str[i+1] == '\\':
result_bytes.append(ord('\\'))
i += 2
elif i + 2 < len(cleaned_str) and re.match(r'[0-9A-Fa-f]{2}', cleaned_str[i+1:i+3]):
hex_val = int(cleaned_str[i+1:i+3], 16)
result_bytes.append(hex_val)
i += 3
else:
result_bytes.append(ord('\\'))
i += 1
else:
result_bytes.append(ord(cleaned_str[i]))
i += 1
try:
# 關鍵轉換:Big5 -> String -> UTF-8 Bytes -> Hex String
chinese_str = result_bytes.decode('big5')
utf8_bytes = chinese_str.encode('utf-8')
return "".join(f"\\{b:02X}" for b in utf8_bytes)
except:
return mt_str
def process_final(input_file):
output_file = input_file.replace('.rsc', '_utf8.rsc')
report_file = input_file.replace('.rsc', '_report.txt')
if not os.path.exists(input_file):
print(f"找不到檔案: {input_file}")
return
with open(input_file, 'r', encoding='ascii', errors='ignore') as f:
full_content = f.read()
report = [f"=== MikroTik 轉換對照報告 (UTF-8 Hex + 路徑上下文) ===",
f"{'指令區塊 (Context Path)':<40} | {'屬性':<10} | {'轉換後中文內容'}", "-" * 110]
current_path = "/"
lines = full_content.splitlines()
output_lines = []
i = 0
while i < len(lines):
line = lines[i]
# 追蹤當前區塊路徑 (如 /ip firewall filter)
path_match = re.match(r'^/([a-zA-Z0-9\-\s]+)', line)
if path_match:
current_path = path_match.group(0).strip()
# 處理跨行屬性 (抓取完整的引號內容)
combined_line = line
temp_idx = i
while (combined_line.count('"') % 2 != 0 or combined_line.endswith('\\')) and temp_idx + 1 < len(lines):
temp_idx += 1
combined_line += "\n" + lines[temp_idx]
# 尋找引號內容並取代
attr_pattern = re.compile(r'(\w+)="([\s\S]*?)"')
new_combined_line = combined_line
matches = list(attr_pattern.finditer(combined_line))
for m in reversed(matches):
key, val = m.groups()
if '\\' in val:
utf8_hex = big5_hex_to_utf8_hex(val)
if utf8_hex != val:
# 為了報告好讀,我們在這裡反解出中文
try:
readable_chinese = bytes.fromhex(utf8_hex.replace('\\', '')).decode('utf-8')
except:
readable_chinese = "解碼失敗"
report.append(f"{current_path[:40]:<40} | {key:<10} | {readable_chinese[:50]}")
start, end = m.span()
new_combined_line = new_combined_line[:start] + f'{key}="{utf8_hex}"' + new_combined_line[end:]
output_lines.append(new_combined_line)
i = temp_idx + 1
# 儲存
with open(output_file, 'w', encoding='ascii') as f:
f.write('\n'.join(output_lines))
with open(report_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(report))
print(f"[*] 處理完畢!")
print(f" - 匯入用檔案: {output_file} (已轉為 UTF-8 Hex)")
print(f" - 對照報告: {report_file} (含路徑上下文)")
if __name__ == "__main__":
process_final('my_config.rsc')
留言