天天看點

OpenWRT UCI介紹及相關處理庫

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​​

​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)是​

    ​example​

    ​,配置名(option)是​

    ​test​

    ​。配置中也允許出現匿名節,即自定義了配置類型,而沒有配置名的節。配置類型對應配置處理程式來說是十分重要的,因為配置程式需要根據這些資訊來處理這些配置項。
  • ​option 'string' 'some value'​

    ​​和 ​

    ​option 'boolean' '1'​

    ​定義了一些簡單值。文本選項和布爾選項在文法上并沒有差異。布爾選項中可以用’0’ , ‘no’, ‘off’, 或者’false’來表示false值,或者也可以用’1’, ‘yes’,'on’或者’true’來表示真值。
  • 以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
}      

6. 常用的庫