OpenWRT UCI介紹及相關處理庫
文章目錄
- OpenWRT UCI介紹及相關處理庫
- 1. 前言
- 2. 概念
- 3. UCI配置檔案
- 4. 檔案文法
- 5. 指令行實用工具
- 5.1 用法
- 5.2 示例
- 導出整個配置
- 檢視所有配置項的值
- 檢視特定選項的值
- 檢視網絡接口的狀态
- 添加防火牆規則
- 5.3 場景示例
- 更改uhttpd監聽端口
- 配置端口轉發
- 6. 常用的庫
1. 前言
基本上OpenWrt上相關的配置都可以使用UCI進行配置,這對我們進行自動化配置路由器相當有幫助,我們可以很友善的将配置過程寫入腳本或者寫入程式,是以這裡大緻總結以下uci常用指令以及一些相關的庫。
2. 概念
UCI系統(https://openwrt.org/zh/docs/guide-user/base-system/uci):
“uci”是“Unified Configuration Interface”(統一配置界面)的縮寫,意在OpenWrt整個系統的配置集中化。
系統配置應容易,更直接且在此有文檔描述,進而使你的生活更輕松!
(它是White Russian系列OpenWrt基于nvram的配置的後繼改進。)
許多程式在系統某處擁有自己的配置檔案,
比如
/etc/network/interfaces
,
/etc/exports
,
/etc/dnsmasq.conf
或者
/etc/samba/samba.conf
,
有時它們還使用稍有不同的文法。
在OpenWrt中你無需為此煩惱,我們隻需更改UCI配置檔案!
你不需要為了某個更改起效而重新開機系統!參閱下文中的指令行實用工具以了解如何做到這點。
還有不要忘了官方程式包(official binaries)裡包含了很多背景程式,但預設情況下并未啟用!
比如cron背景程式預設并未激活,因而隻編輯crontab并無作用。
你需要用
/etc/init.d/crond start
起動它或用
/etc/init.d/crond enable
激活它。 大部分背景程式都可以
disable
(禁用),
stop
(停止)和
restart
(重起)。 還有一些非UCI配置你可以參閱。
3. UCI配置檔案
OpenWrt的所有配置檔案皆位于/etc/config/目錄下。每個檔案大緻與它所配置的那部分系統相關。可用文本編輯器、“uci” 指令行實用程式或各種程式設計API(比如 Shell, Lua and C)來編輯/修改這些配置檔案。
檔案位置 | 描述 |
基本配置 | |
/etc/config/dhcp | dnsmasq和DHCP的配置 |
/etc/config/dropbear | SSH服務端選項 |
/etc/config/firewall | 中央防火牆配置 |
/etc/config/network | 交換,接口和路由配置 |
/etc/config/system | 雜項與系統配置 |
/etc/config/timeserver | rdate的時間伺服器清單 |
/etc/config/wireless | 無線設定和無線網絡的定義 |
IPv6 | |
/etc/config/ahcpd | Ad-Hoc配置協定(AHCP) 服務端配置以及轉發器配置 |
/etc/config/aiccu | AICCU 用戶端配置 |
/etc/config/dhcp6c | WIDE-DHCPv6 用戶端配置 |
/etc/config/dhcp6s | WIDE-DHCPv6 服務端配置 |
/etc/config/gw6c | GW6c 用戶端配置 |
/etc/config/radvd | 路由通告 (radvd) 配置 |
其他 | |
/etc/config/etherwake | 以太網喚醒: etherwake |
/etc/config/fstab | 挂載點及swap |
/etc/config/hd-idle | 另一個可選的硬碟空閑休眠程序(需要路由器支援usb硬碟) |
/etc/config/httpd | 網頁伺服器配置選項(Busybox 自帶httpd, 已被舍棄) |
/etc/config/luci | 基礎 LuCI 配置 |
/etc/config/luci_statistics | 包統計配置 |
/etc/config/mini_snmpd | mini_snmpd 配置 |
/etc/config/mountd | OpenWrt 自動挂載程序(類似autofs) |
/etc/config/multiwan | 簡單多WAN出口配置 |
/etc/config/ntpclient | ntp用戶端配置,用以擷取正确時間 |
/etc/config/pure-ftpd | Pure-FTPd 服務端配置 |
/etc/config/qos | QoS配置(流量限制與整形) |
/etc/config/samba | samba配置(Microsoft檔案共享) |
/etc/config/snmpd | SNMPd(snmp服務程序) 配置 |
/etc/config/sshtunnel | 配置 |
/etc/config/stund | STUN 服務端配置 |
/etc/config/transmission | BitTorrent配置 |
/etc/config/uhttpd | Web伺服器配置(uHTTPd) |
/etc/config/upnpd | miniupnpd UPnP伺服器配置 |
/etc/config/ushare | uShare UPnP 伺服器配置 |
/etc/config/vblade | vblade 使用者空間AOE(ATA over Ethernet)配置 |
/etc/config/vnstat | vnstat 下載下傳器配置 |
/etc/config/wifitoogle | 使用按鈕來開關WiFi的腳本 |
/etc/config/wol | Wake-on-Lan: wol |
/etc/config/znc | ZNC 配置 |
4. 檔案文法
在UCI的配置檔案通常包含一個或多個配置語句,包含一個或多個用來定義實際值的選項語句的所謂的節。
下面是一個簡單的配置示例檔案:
package 'example'
config 'example' 'test'
option 'string' 'some value'
option 'boolean' '1'
list 'collection' 'first item'
list 'collection' 'second item'
- config ‘example’ ‘test’ 語句标志着一個節(section)的開始。這裡的配置類型(secType)是
,配置名(option)是example
。配置中也允許出現匿名節,即自定義了配置類型,而沒有配置名的節。配置類型對應配置處理程式來說是十分重要的,因為配置程式需要根據這些資訊來處理這些配置項。test
-
和 option 'string' 'some value'
定義了一些簡單值。文本選項和布爾選項在文法上并沒有差異。布爾選項中可以用’0’ , ‘no’, ‘off’, 或者’false’來表示false值,或者也可以用’1’, ‘yes’,'on’或者’true’來表示真值。option 'boolean' '1'
- 以list關鍵字開頭的多個行,可用于定義包含多個值的選項。所有共享一個名稱的list語句,會組裝形成一個值清單,清單中每個值出現的順序,和它在配置檔案中的順序相同。如上例中,清單的名稱是’collection’,它包含了兩個值,即’first item’和’second item’。
- 'option’和’list’語句的縮進可以增加配置檔案的可讀性,但是在文法不是必須的。
通常不需要為辨別符和值加引号,隻有當值包括空格或者制表符的時候,才必須加引号。同時,在使用引号的時候,可以用雙引号代替單引号。
下面列舉的例子都是符合uci文法的正确配置:
-
option example value
-
option 'example' value
-
option example “value”
-
option “example” 'value'
-
option 'example' “value”
反之,以下配置則存在文法錯誤
-
(引号不比對)option 'example“ “value'
-
(值中包含空格,需要為值加引号)option example some value with space
還有一點是必須知道的,即UCI辨別符和配置檔案名稱所包含的字元必須是由
a-z
,
0-9
和
_
組成。 選項值則可以包含任意字元,隻要這個值是加了引号的。
5. 指令行實用工具
使用awk、grep等指令來解析Openwrt的配置檔案是低效和不明智的做法,建議使用者通過uci工具對openwrt進行配置。
下面将給出一些例子,來展示uci這個強大的工具。
5.1 用法
root@OpenWrt:~# uci
Usage: uci [<options>] <command> [<arguments>]
Commands:
batch
export [<config>]
import [<config>]
changes [<config>]
commit [<config>]
add <config> <section-type>
add_list <config>.<section>.<option>=<string>
del_list <config>.<section>.<option>=<string>
show [<config>[.<section>[.<option>]]]
get <config>.<section>[.<option>]
set <config>.<section>[.<option>]=<value>
delete <config>[.<section>[[.<option>][=<id>]]]
rename <config>.<section>[.<option>]=<name>
revert <config>[.<section>[.<option>]]
reorder <config>.<section>=<position>
Options:
-c <path> set the search path for config files (default: /etc/config)
-d <str> set the delimiter for list values in uci show
-f <file> use <file> as input instead of stdin
-m when importing, merge data into an existing package
-n name unnamed sections on export (default)
-N don't name unnamed sections
-p <path> add a search path for config change files
-P <path> add a search path for config change files and use as default
-q quiet mode (don't print error messages)
-s force strict mode (stop on parser errors, default)
-S disable strict mode
-X do not use extended syntax on 'show'
5.2 示例
導出整個配置
root@OpenWrt:~# uci export uhttpd
package uhttpd
config uhttpd 'main'
list listen_https '0.0.0.0:443'
list listen_https '[::]:443'
option redirect_https '0'
option home '/www'
option rfc1918_filter '0'
option max_requests '3'
option max_connections '100'
option cert '/etc/uhttpd.crt'
option key '/etc/uhttpd.key'
option cgi_prefix '/cgi-bin'
list lua_prefix '/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua'
option script_timeout '60'
option network_timeout '30'
option http_keepalive '20'
option tcp_keepalive '1'
list listen_http '0.0.0.0:81'
list listen_http '[::]:81'
list listen_http '0.0.0.0:8082'
config cert 'defaults'
option days '730'
option key_type 'rsa'
option bits '2048'
option ec_curve 'P-256'
option country 'ZZ'
option state 'Somewhere'
option location 'Unknown'
option commonname 'OpenWrt'
檢視所有配置項的值
root@OpenWrt:~# uci show uhttpd
uhttpd.main=uhttpd
uhttpd.main.listen_https='0.0.0.0:443' '[::]:443'
uhttpd.main.redirect_https='0'
uhttpd.main.home='/www'
uhttpd.main.rfc1918_filter='0'
uhttpd.main.max_requests='3'
uhttpd.main.max_connections='100'
uhttpd.main.cert='/etc/uhttpd.crt'
uhttpd.main.key='/etc/uhttpd.key'
uhttpd.main.cgi_prefix='/cgi-bin'
uhttpd.main.lua_prefix='/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua'
uhttpd.main.script_timeout='60'
uhttpd.main.network_timeout='30'
uhttpd.main.http_keepalive='20'
uhttpd.main.tcp_keepalive='1'
uhttpd.main.listen_http='0.0.0.0:81' '[::]:81' '0.0.0.0:8082'
uhttpd.defaults=cert
uhttpd.defaults.days='730'
uhttpd.defaults.key_type='rsa'
uhttpd.defaults.bits='2048'
uhttpd.defaults.ec_curve='P-256'
uhttpd.defaults.country='ZZ'
uhttpd.defaults.state='Somewhere'
uhttpd.defaults.location='Unknown'
uhttpd.defaults.commonname='OpenWrt'
檢視特定選項的值
root@OpenWrt:~# uci get uhttpd.@uhttpd[0].listen_http
0.0.0.0:81 [::]:81 0.0.0.0:8082
檢視網絡接口的狀态
root@OpenWrt:~# uci -P/var/state show network.wan
network.wan=interface
network.wan.ifname='eth7'
network.wan.proto='dhcp'
root@OpenWrt:~# uci -P/var/state show network.wan_eth
network.wan_eth=interface
network.wan_eth.ifname='eth0'
network.wan_eth.proto='static'
network.wan_eth.netmask='255.255.255.0'
network.wan_eth.gateway='192.168.67.254'
network.wan_eth.dns='8.8.8.8'
network.wan_eth.ipaddr='192.168.67.87'
network.wan_eth.up='1'
添加防火牆規則
這是一個添加SSH端口轉發到防火牆規則的例子,和’-1’使用的一個例子。
root@OpenWrt:~# uci add firewall rule
root@OpenWrt:~# uci set firewall.@rule[-1].src=wan
root@OpenWrt:~# uci set firewall.@rule[-1].target=ACCEPT
root@OpenWrt:~# uci set firewall.@rule[-1].proto=tcp
root@OpenWrt:~# uci set firewall.@rule[-1].dest_port=22
root@OpenWrt:~# uci commit firewall
root@OpenWrt:~# /etc/init.d/firewall restart
5.3 場景示例
更改uhttpd監聽端口
比如我們要将我們的配置web配置到80端口,這就需要更改uhttpd預設監聽的80端口為其它端口,這裡就可以将該更改uhttpd監聽80端口更改為81端口的過程寫入shell腳本執行,以此友善一鍵化部署配置web(當然實際批量生産時打包固件即可),如下是将該過程簡單寫為shell函數的代碼(會将原本的uhttpd配置檔案備份,然後判斷相關端口是否被監聽,是則删除後增加,由于list沒有更改功能是以實用删除後增加的方式進行修改):
# 利用uci指令修改uhttpd對80端口和8080端口的監聽,便于nginx監聽80端口友善通路自研配置web
function uhttpd_uci_conf() {
echo "--------------------設定uhttpd監聽端口---------------"
uhttpd_back="/etc/config/uhttpd_back"
# 這裡的-f參數判斷$myFile是否存在
if [ ! -f "$uhttpd_back" ]; then
cp /etc/config/uhttpd $uhttpd_back
fi
echo "###old uhttpd info:"
uci show uhttpd
listen_http1='0.0.0.0:80'
listen_http2='[::]:80'
listen_http3='0.0.0.0:8080'
if ! grep "$listen_http1" /etc/config/uhttpd >/dev/null
then
#不存在,不做處理
echo "uhttpd not listen 80 port."
else
#存在,删除,然後添加81端口
uci del_list uhttpd.main.listen_http='0.0.0.0:80'
uci del_list uhttpd.main.listen_http='[::]:80'
uci del_list uhttpd.main.listen_http='0.0.0.0:8080'
uci add_list uhttpd.main.listen_http='0.0.0.0:81'
uci add_list uhttpd.main.listen_http='[::]:81'
uci add_list uhttpd.main.listen_http='0.0.0.0:8082'
uci commit
echo "###new uhttpd info:"
uci show uhttpd
fi
echo "--------------------設定uhttpd監聽端口完成-----------"
}
配置端口轉發
此外,可以設想一下如下場景,我們将家裡某個子裝置PC當成伺服器,而該PC的外網IP取決于路由器配置的外網IP,這時我們可以将PC的IP設定為靜态IP,然後将其某些端口映射到路由器的外網IP某些端口上,這樣我們就可以通路外網IP某個端口來通路PC上的對應端口了,一些大的資源不用放在路由器上我們外網也可以通路,搭建個人雲盤、個人伺服器都變得可行(自媒體這麼火,在隐私越來越重視的情況下,我想未來将伺服器、網盤等都建立在自己家中這種事也會有一定的市場空間,而ipv6普及之後外網IP的制約條件也會消失)。
這裡是一個簡單的端口映射shell腳本函數(可以将這些參數以外部傳參的方式或者配置檔案的形式讀取都可以):
function add_redirect() {
uci add firewall redirect
uci set firewall.@redirect[-1].dest_port='80'
uci set firewall.@redirect[-1].src='wan'
uci set firewall.@redirect[-1].src_dport='10080'
uci set firewall.@redirect[-1].target='DNAT'
uci set firewall.@redirect[-1].dest_ip='192.168.1.200'
uci set firewall.@redirect[-1].dest='lan'
uci commit
/etc/init.d/firewall restart
uci show firewall
}