openwrt-dnsforwarder: remove luci

This commit is contained in:
CN_SZTL 2019-11-24 13:27:24 +08:00
parent 7d1a154584
commit c0a008438d
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
21 changed files with 0 additions and 10655 deletions

View File

@ -9,10 +9,8 @@ PKG_SOURCE_URL:=https://github.com/holmium/dnsforwarder.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=587e61ae4d75dc976f538088b715a3c8ee26c144
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-6
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
@ -27,35 +25,12 @@ define Package/$(PKG_NAME)/description
Forwarding queries to customized domains (and their subdomains) to specified servers over a specified protocol (UDP or TCP). non-standard ports are supported.
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
rm -rf /tmp/luci*
endef
define Package/$(PKG_NAME)/conffiles
/etc/dnsforwarder/dnsforwarder.conf
/etc/dnsforwarder/china-banned
/etc/dnsforwarder/base-gfwlist.txt
/etc/dnsforwarder/userlist
endef
define Build/Prepare
$(Build/Prepare/Default)
$(foreach po,$(wildcard ${CURDIR}/i18n/zh-cn/*.po), \
po2lmo $(po) $(PKG_BUILD_DIR)/$(patsubst %.po,%.lmo,$(notdir $(po)));)
endef
CONFIGURE_ARGS += --enable-downloader=wget
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/dnsforwarder $(1)/usr/bin/dnsforwarder
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
$(INSTALL_DATA) $(PKG_BUILD_DIR)/*.*.lmo $(1)/usr/lib/lua/luci/i18n/
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -1,75 +0,0 @@
# openwrt-dnsforwarder
为OpenWRT路由器编译运行[dnsforwarder][A]编写的Makefile和luci界面
简介
---
本软件包为OpenWRT路由器使用dnsforwarder配置企业级DNS服务器并与dnsmasq配合进行智能黑名单解析的工具
1、支持在Web界面编辑dnsforwarder配置文件
2、支持在Web界面编辑GFWList名单和自定义的黑白名单
3、可以控制iptables对客户端发来的DNS请求进行劫持
4、与DNSMasq配合进行给予黑白名单的DNS请求转发
5、与DNSMasq配合将黑白名单中的域名解析完成后添加到ipset为SSR路由提供依据
6、支持一键升级GFWList黑名单
依赖
---
显式依赖 `wget`用于加载网络上的host文件
配置
---
配置文件地址 "/etc/dnsforwarer/dnsfrowarder.conf"
GFWList地址 "/etc/dnsforwarer/base-gfwlist.txt"
用户自定义黑名单 “/etc/dnsforwarer/userlist”
用户自定义白名单 “etc/dnsforwarer/whitelist”
编译
---
从 OpenWrt 的 [SDK][openwrt-sdk] 编译
```bash
# 解压下载好的 SDK
tar xjf OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2
cd OpenWrt-SDK-ar71xx-*
# Clone 项目
git clone https://github.com/AlexZhuo/openwrt-dnsforwarder/ package/dnsforwarder
# 编译 po2lmo (如果有po2lmo可跳过)
pushd package/dnsforwarder/tools/po2lmo
make && sudo make install
popd
# 选择要编译的包 Network -> dnsforwarder
make menuconfig
# 开始编译
make package/dnsforwarder/compile V=99
```
截图
---
![demo](https://github.com/AlexZhuo/openwrt-dnsforwarder/raw/master/screencapture-192-168-167-101-cgi-bin-luci-admin-services-dnsforwarder-1509669292068.png)
![demo](https://github.com/AlexZhuo/openwrt-dnsforwarder/raw/master/screencapture-192-168-167-102-cgi-bin-luci-admin-services-dnsforwarder-gfwlist-1509575828363.png)
![demo](https://github.com/AlexZhuo/openwrt-dnsforwarder/raw/master/screencapture-192-168-167-101-cgi-bin-luci-admin-services-dnsforwarder-log-1509669318124.png)
[A]: https://github.com/holmium/dnsforwarder
[openwrt-sdk]: https://wiki.openwrt.org/doc/howto/obtain.firmware.sdk

View File

@ -1,5 +0,0 @@
config arguments
option enabled '0'
option redir '0'

View File

@ -1,434 +0,0 @@
# DNS 转发器的配置文件
# Configuration File for dnsforwarder
# 此配置文件最好是 ANSI 编码的
# 相对路径的写法
# Windows
# 支持用 `% %' 包围起来的相对路径,比如 `%SYSTEMROOT%\System32\drivers\etc\hosts'。
# `%PROGRAMDIRECTORY%' 表示程序所在的文件夹。
# `%CONFIGFILEDIRECTORY%' 表示配置文件所在的文件夹。 (since 6.1.3)
#
# Linux
# 支持类似 `${HOME}' 的变量,比如 `${HOME}/hosts'。
# `${PROGRAMDIRECTORY}' 表示程序的配置文件夹,一般为 `/root/.dnsforwarder/',执行 `dnsforwarder -p' 可以获得具体的位置。
# `${CONFIGFILEDIRECTORY}' 表示配置文件所在的文件夹。 (since 6.1.3)
##################################################
#
# 日志文件设置
#
##################################################
# LogOn <BOOLEAN>
# 是否打开文件日志输出 (since 5.0.4)
LogOn true
# LogFileThresholdLength <NUM>
# 单个日志文件大小的临界值(字节)(since 5.0.4)
# 当日志文件大小超过这个临界值后,当前的日志文件将会被重命名,然后建立一个新的日志文件,继续记录日志
LogFileThresholdLength 102400
# LogFileFolder <PATH>
# 设定日志文件所在的文件夹 (since 5.0.4)
# 日志文件初始的文件名为 `dnsforwarder.log',当超过临界值之后,将会被重命名为 `dnsforwarder.log.1'、`dnsforwarder.log.2' 等等,然后重新建立一个 dnsforwarder.log' 文件
# 此路径的默认值为程序所在的文件夹Windows或程序的配置文件夹Linux
LogFileFolder /var/log
##################################################
#
# 本地
#
##################################################
# UDPLocal <IP[:PORT]>,<IP[:PORT]>,...
# 设置在本地开启的接口的IP地址和端口可以是本地回环地址 (127.0.0.1) ,本地局域网,以及互联网 (since 6.0.0)
# 如果是 IPv6 地址请在IP两端加上方括号不包含端口部分例如 [::1]:53 (本地回环)、[fe80::699c:f79a:9bb6:1]:5353 (since 6.0.0)
# 可以设置多个地址,用半角逗号(`,')分割
# 如果不指定端口,则默认为 53
#
# 示例:
# UDPLocal 127.0.0.1:53,[::1]:53
UDPLocal 0.0.0.0:5053
# 这一版本暂时不支持在本地开启 TCP 端口,以后会加上
##################################################
#
# IP 选择策略
#
##################################################
#########################
# 服务器地址
#########################
# UDPGroup <IP1[:PORT],IP2[:PORT],...> <DOMAIN1,DOMAIN2,...> <on|off>
# 设置一个 UDP 上游服务器组,并指定通过这些上游服务器查询的域名 (since 6.0.0)
# 第一部分参数“<IP1[:PORT],IP2[:PORT],...>”,用于指定 UDP 上游服务器,不写端口则默认使用 53 端口
# 第二部分参数“<DOMAIN1,DOMAIN2,...>”,用于指定通过这些 UDP 上游服务器查询的域名,可以包含通配符
# 第三部分参数“<on|off>”,用于指定是否开启并发查询,`on' 为开启,`off' 为不开启
# 并发查询指的是,向所有指定的 UDP 服务器发送查询请求,取最先接受到的未屏蔽的回复作为查询结果,并丢弃其余的回复
# 可以有多条 `UDPGroup' 选项
UDPGroup 1.0.0.1,1.1.1.1,4.2.2.1,4.2.2.2,1.2.4.8,210.2.4.8,8.8.4.4,8.8.8.8,9.9.9.9,119.29.29.29,119.28.28.28,223.5.5.5,223.6.6.6,114.114.114.114,114.114.115.115,180.76.76.76,208.67.222.222,208.67.220.220,1.0.0.1:443,1.1.1.1:443,1.0.0.1:853,1.1.1.1:853,208.67.222.222:443,208.67.220.220:443,208.67.222.222:5353,208.67.220.220:5353,127.0.0.1:5353,240c::6666,240c::6644,2001:4860:4860::8844,2001:4860:4860::8888,2606:4700:4700::1111,2606:4700:4700::1001 * on
# TCPGroup <IP1[:PORT],IP2[:PORT],...> <DOMAIN1,DOMAIN2,...> <no|PROXY1[:PORT],PROXY2[:PORT],...>
# 设置一个 TCP 上游服务器组,并指定通过这些上游服务器查询的域名 (since 6.0.0)
# 第一部分参数“<IP1[:PORT],IP2[:PORT],...>”,用于指定 TCP 上游服务器,不写端口则默认使用 53 端口
# 第二部分参数“<DOMAIN1,DOMAIN2,...>”,用于指定通过这些 TCP 上游服务器查询的域名,可以包含通配符
# 第三部分参数“<no|PROXY1[:PORT],PROXY2[:PORT],...>”,用于指定查询时使用的 Socks5 代理,不写端口则默认使用 1080 端口。`no' 代表不使用代理
# 可以有多条 `TCPGroup' 选项
#
# 示例一:
# TCPGroup 1.2.4.8:53,114.114.114.114 *.example.com 192.168.50.5:8080,192.168.50.6:8080
# `*.example.com' 将通过 192.168.50.5:8080 或 192.168.50.6:8080 两个 Socks5 代理,使用 TCP 协议向 1.2.4.8:53 或 114.114.114.114 进行查询
# 示例二:
# TCPGroup 8.8.8.8,114.114.114.114:53 * no
# `*.example.com' 将使用 TCP 协议直接向 8.8.8.8 或 114.114.114.114:53 进行查询,不使用代理
TCPGroup 1.0.0.1,1.1.1.1,4.2.2.1,4.2.2.2,1.2.4.8,210.2.4.8,8.8.4.4,8.8.8.8,9.9.9.9,119.29.29.29,119.28.28.28,223.5.5.5,223.6.6.6,114.114.114.114,114.114.115.115,180.76.76.76,208.67.222.222,208.67.220.220,1.0.0.1:443,1.1.1.1:443,1.0.0.1:853,1.1.1.1:853,208.67.222.222:443,208.67.220.220:443,208.67.222.222:5353,208.67.220.220:5353,240c::6666,240c::6644,2001:4860:4860::8844,2001:4860:4860::8888,2606:4700:4700::1111,2606:4700:4700::1001 * no
# GroupFile <PATH>
# 从文件加载服务器组 (since 6.1.3)
# 服务器组文件的写法请参阅https://github.com/holmium/dnsforwarder/wiki/GroupFile-%E7%9A%84%E5%86%99%E6%B3%95-%7C-How-to-write-GroupFiles
# 可以有多条 `GroupFile' 选项
#
# 示例一:
# GroupFile D:\group.txt
#
# 示例二:
# GroupFile /etc/group.txt
GroupFile
# 注意:
# 1.对于没有指定服务器的域名,会随机选择一个服务器组进行查询。
# 2.如果某域名匹配多个服务器组,则选择的顺序如下:
# (1) 优先选择不含通配符的匹配项,如果仍然有多条匹配,则选择匹配度最高的那个,
# 如果匹配度相同的情况下仍然有多条匹配,则选择最后一个。
# (例如 `ipv6.microsoft.com' 比 `microsoft.com' 对于域名 `teredo.ipv6.microsoft.com' 的匹配度更高)
# (2) 然后选择包含通配符的匹配项,如果有多条匹配,则选择第一个;
# 组合示例:
# 一、以 microsoft.com 或 office.com 结尾的域名通过 UDP 服务器 1.2.4.8 查询,其它域名通过 TCP 服务器 8.8.4.4 查询:
# UDPGroup 1.2.4.8 microsoft.com,office.com on
# TCPGroup 8.8.4.4 * no
# 两行顺序请保持一致
#########################
# 服务器选项
#########################
# BlockIP <IP1>,<IP2>,.....
# 阻挡含有以下 IP 地址(支持 IPv4 和 IPv6 地址)的 DNS 数据包 (since 6.0.0)
# IPv6 地址不用加方括号
BlockIP 243.185.187.39,46.82.174.68,37.61.54.158,93.46.8.89,59.24.3.173,203.98.7.65,8.7.198.45,78.16.49.15,159.106.121.75,69.63.187.12,31.13.76.8,31.13.64.49
# IPSubstituting <IP1 IP'1>,<IP2 IP'2>,.....
# 替换 DNS 数据包中的 IP 地址(只支持 IPv4 地址) (since 5.0.1)
# 例如:
# IPSubstituting 127.0.0.1 1.2.0.127
# 的效果是把 DNS 数据包中所有的 127.0.0.1 地址替换为 1.2.0.127
# 仅替换通过服务器TCP 和 UDP查询而来的 DNS 数据包,对于缓存中和 Hosts 中的结果无效
# 多条替换项目用半角逗号 (`,') 分隔,也可以写多行 `IPSubstituting'
IPSubstituting
# BlockNegativeResponse <BOOLEAN>
# 是否过滤来自上游服务器的查询未成功的响应 (since 6.1.1)
# 查询未成功指:格式错误、服务器错误、域名不存在和服务器拒绝请求等
# 参见 RFC 6895`2.3. RCODE Assignment'
BlockNegativeResponse false
#########################
# IP 列表(仅支持 IPv4 地址)
#########################
# IP 列表用于自动检测一组 IP 地址,将相应最快的 IP 地址甄选出来
# GoodIPList <NAME> <INTERVAL>
# 定义一个 IP 列表,<NAME> 为改列表的名称,<INTERVAL> 为检测列表中 IP 地址有效性的间隔时间(毫秒)
# 例如:
# GoodIPList list1 60000
# GoodIPListAddIP <LIST_NAME> <IP:PORT>
# 向一个 IP 列表中添加 IP 地址
# 例如:
# GoodIPListAddIP list1 120.0.0.1:80
#########################
# Hosts
#########################
# Hosts <STRING>
# Hosts 文件的 URL可以是本地 Hosts 文件 (以 file:// 开头,支持相对路径),也可以是网络上的 Hosts 文件 (以 http:// 或者 https:// 开头)。 (since 5.0.5)
# 例如 file://C:/Windows/System32/drivers/etc/hosts 或 file:///etc/hosts 或 http://xxx.com/hosts
# 写多条 `Hosts' 可以指定多个 Hosts 文件,路径两头不要加引号
# 在 Hosts 文件中,支持通配符 (`*' 和 `?') (只能在域名中出现通配符)
# Hosts 文件必须是原始格式,不能是压缩文件或者 HTML 文件
# Hosts 文件最好是 ANSI 编码的
# Hosts 中的 IPv6 地址不用加方括号
# 如果保留为空,则不从文件载入 Hosts
Hosts
# HostsUpdateInterval <NUM>
# 重新载入 Hosts 文件的间隔时间,秒 (since 2.2)
# -1 表示不重新载入
# 如果保留为空,则使用默认值 (18000)
HostsUpdateInterval 18000
# HostsDownloadPath <PATH>
# Hosts 文件的下载到本地文件的路径 (不是文件夹路径) (since 2.2)
# 例如 C:\Windows\Temp\hosts 或者 /tmp/hosts
# 支持相对路径 (since 5.0.3)
# 如果文件存在则覆盖
# 如果保留为空则默认在与程序所在相同的文件夹内Windows或程序的配置文件夹内Linux
HostsDownloadPath
# HostsScript <PATH>
# 在每次下载完 Hosts 文件后、加载 Hosts 文件之前执行的脚本 (since 2.2)
# 支持相对路径 (since 5.0.3)
# 如果保留为空,则不执行脚本
HostsScript
# HostsRetryInterval <NUM>
# 当网络 Hosts 下载失败后的重试时间,秒 (since 2.2.2)
# 仅对网络 Hosts 有效
# 如果保留为空,则使用默认值 (30)
HostsRetryInterval 30
# AppendHosts <HOSTS>,<HOSTS>,...
# 附加的 hosts即使 `Hosts' 选项为空也照样载入 (since 2.2.2)
# <HOSTS> 的写法与文件中的一样,同样支持通配符
# IPv6 地址不用加方括号
# 多条 hosts 可以用半角逗号分隔开,也可以写多条 `AppendHosts'
# 比如可以写成:
# AppendHosts 127.0.0.1 123.com,127.0.0.1 456.com,1.2.3.4 foobar.*
# 也可以分多条写:
# AppendHosts 127.0.0.1 123.com
# AppendHosts 127.0.0.1 456.com
# AppendHosts 1.2.3.4 foobar.*
#
# 也可以定义指向一个 IP 列表的 Hosts 项(仅支持 IPv4 地址),例如:
# AppendHosts <list1> www.123.com
# 此时 www.123.com 将会指向 list1 中最快的 IP 地址。
#
# 也可以定义 CName 的 Hosts 项,例如:
# AppendHosts www.google.cn *.google.com
# 这样所有匹配 *.google.com 的域名都将指向 www.google.cn 的 IP 地址 (since 2.3)
#
# 如果使某些域名跳过在 hosts 中的查询,可以
# AppendHosts @@ *.012345.com
# 这样所有匹配 *.012345.com 的域名都不会在 hosts 中查询
#
# 各种 hosts 的优先级从高到低
# 带 `@@' 的禁止项
# 一般 hosts 项
# CName hosts 项
AppendHosts
# BlockIpv6WhenIpv4Exists <BOOLEAN>
# 如果一个域名在 Hosts 被指定了一个 IPv4 地址(包括文件 Hosts 和 `AppendHosts' 指定的 Hosts那么拒绝对这个域名的 IPv6 地址查询 (since 5.0.12, renamed after 6.0.0)
BlockIpv6WhenIpv4Exists false
##################################################
#
# 缓存控制
#
##################################################
# UseCache <BOOLEAN>
# 是否使用缓存(默认为文件缓存) (since 2.2)
# 可选值:`false' 或 `true'
UseCache false
# CacheSize <NUM>
# 缓存大小 (字节)
# 缓存大小不能小于 102400 (100KB) (since 2.3)
CacheSize 1048576
# MemoryCache <BOOLEAN>
# 是否使用内存缓存,而不是文件缓存 (since 2.3.2)
# 如果 `UseCache' 为 `false',此选项无效
# 可选值:`false' 或 `true'
MemoryCache true
# CacheFile <PATH>
# 手工指定缓存文件 (不是文件夹) (since 2.3)
# 支持相对路径 (since 5.0.3)
# 如果保留为空则默认在与程序所在相同的文件夹内Windows或程序的配置文件夹内Linux
# 如果 `MemoryCache' 为 `true',此选项无效
CacheFile
# IgnoreTTL <BOOLEAN>
# 是否忽略 TTL (since 2.2)
# 可选值:`false' 或 `true'
# 为 `true' 时将忽略 TTL此时所有的缓存条目将不会被移除
# 为 `false' 时不忽略 TTL缓存条目将会按照 TTL 的时间来移除
# 当 `UseCache' 的值为 `false' 时,此选项无效
IgnoreTTL false
# OverrideTTL <NUM>
# 强制使所有缓存的条目的 TTL 为 <NUM> (since 2.2)
# 若 <NUM> 为 -1则表示不进行强制
# 当 `UseCache' 的值为 `false' 时,此选项无效
# 此选项等同于 `CacheControl * fixed <NUM>' (since 5.0.18)
OverrideTTL -1
# MultipleTTL <NUM>
# 将所有缓存条目的 TTL 加倍,倍数为 <NUM> (since 2.2)
# 当 `UseCache' 的值为 `false' 时,此选项无效
# 当 `IgnoreTTL' 的值为 `true' 时,此选项无效
# 此选项等同于 `CacheControl * vari <NUM>x+0' (since 5.0.18)
MultipleTTL 1
# CacheControl <DOMAIN> [$[$]]<TYPE> [ARGUMENT]
# 控制域名 <DOMAIN> 的缓存行为 (since 5.0.18)
# 如果缓存未开启,则此选项无效
# <DOMAIN> 是域名;[$[$]] 是传染设定;<TYPE> 是类型;[ARGUMENT] 是参数
# <DOMAIN> 支持通配符,支持尾部匹配
# <TYPE> 有以下可选项(均为小写):
# orig : 使用原先的 TTL即不改变指定域名记录的 TTL此类型无需 [ARGUMENT] 参数
# nocache : 不缓存指定域名记录,此类型无需 [ARGUMENT] 参数
# fixed : 将指定域名记录的 TTL 修改为一个预先指定的常数值,这个值通过 [ARGUMENT] 参数指定
# vari : 将指定域名记录的 TTL 修改为一个预先规定的变量,这个变量通过 [ARGUMENT] 参数指定,此时 [ARGUMENT] 参数的格式为 `ax+b',其中 a、b 为非负整数需用户手工指定x 为记录原先的 TTL 值(不需要用户指定)。此选项必须为 `ax+b' 的形式,不能是 `ax-b' 或者其它的变体形式
#
# 示例:
# CacheControl baidu.com orig # 不改变以 `baidu.com' 结尾的域名的 TTL
# CacheControl 163.com nocache # 不缓存以 `163.com' 结尾的域名
# CacheControl qq.com fixed 500 # 把所有以 `qq.com' 结尾的域名的 TTL 修改为 500
# CacheControl sina.com.cn vari 2x+200 # 把所有以 `sina.com.cn' 结尾的域名的 TTL 的值修改为 2x+200其中 x 是域名记录原先的 TTL 值
#
# 传染机制:
# 某些域名有 CName 记录,例如 www.windowsupdate.com
# ;; QUESTION SECTION:
# ;www.windowsupdate.com. IN A
#
# ;; ANSWER SECTION:
# www.windowsupdate.com. 3585 IN CNAME windowsupdate.microsoft.nsatc.net. (记录一)
# windowsupdate.microsoft.nsatc.net. 285 IN CNAME www.update.microsoft.com.nsatc.net. (记录二)
# www.update.microsoft.com.nsatc.net. 285 IN A 134.170.58.222 (记录三)
# www.update.microsoft.com.nsatc.net. 285 IN A 65.55.50.157 (记录四)
#
# 如果仅仅指定了 `www.windowsupdate.com' 的缓存控制,那么 `windowsupdate.microsoft.nsatc.net' 和 `www.update.microsoft.com.nsatc.net' 的记录以什么规则进行处理?是继承 `www.windowsupdate.com' 的缓存设置,还是使用自己专门的设置(如果有的话)?
# 可以指定传染机制来解决这个问题
# 有以下传染机制(以 `www.windowsupdate.com' 为例):
# 主动传染 : 所有的域名记录不论是否存在单独指定的控制条目,均使用 `www.windowsupdate.com' 的控制条目
# 被动传染 : 如果存在单独指定的控制条目,那么使用单独指定的控制条目,否则使用 `www.windowsupdate.com' 的控制条目
# 不传染 : 如果存在单独指定的控制条目,那么使用单独指定的控制条目,如果没有则不修改记录的 TTL 值
# 只有被查询的域名控制条目才具有传染性质
# 写法:
# 主动传染 (此为默认情况):
# CacheControl www.windowsupdate.com fixed 1000
# CacheControl 163.com orig
# 被动传染(<TYPE> 前加一个 `$':
# CacheControl www.windowsupdate.com $fixed 1500
# CacheControl sina.com.cn $nocache
# 不传染(<TYPE> 前加两个 `$':
# CacheControl www.windowsupdate.com $$fixed 2000
# CacheControl windowsupdate.microsoft.nsatc.net $$vari 2x+100
#
# 示例(仍然以 `www.windowsupdate.com' 为例):
# CacheControl www.windowsupdate.com fixed 1000
# CacheControl windowsupdate.microsoft.nsatc.net fixed 500
# 效果是:记录一、二、三和四的 TTL 都会被修改为 1000
#
# CacheControl www.windowsupdate.com $fixed 1000
# CacheControl windowsupdate.microsoft.nsatc.net fixed 500
# 效果是:记录一、三和四的 TTL 会被修改为 1000记录二的 TTL 会被修改为 500
#
# CacheControl www.windowsupdate.com $$fixed 1000
# CacheControl windowsupdate.microsoft.nsatc.net fixed 500
# 效果是:记录一的 TTL 会被修改为 1000记录二的 TTL 会被修改为 500记录三和四的 TTL 不会被修改
# ReloadCache <BOOLEAN>
# 当程序启动时是否重新载入已有的文件缓存 (since 2.2.3)
# 已有的缓存大小必须和 `CacheSize' 所指定的大小相等
# 可选值:`false' 或 `true'
# 如果 `MemoryCache' 的值为 `true',此选项无效
ReloadCache false
# OverwriteCache <BOOLEAN>
# 如果已有的文件缓存无法重载,是否直接将其覆盖掉 (since 2.3)
# 可选值:`false' 或 `true'
# 如果 `MemoryCache' 的值为 `true',此选项无效
# 如果 `ReloadCache' 的值为 `false',此选项无效
OverwriteCache false
##################################################
#
# 杂项
#
##################################################
# DisabledType <NUM1>,<NUM2>,.....
# 禁止查询的 DNS 类型列表,每个类型(用数字代表)之间用半角逗号 (`,') 分隔 (since 2.2)
# 所有的 DNS 类型:
# A 1 IPv4 地址
# AAAA 28 IPv6 地址
# APL 42
# CERT 37
# CNAME 5
# DHCID 49
# DLV 32769
# DNAME 39
# DNSKEY 48
# DS 43
# HIP 55
# IPSECKEY 45
# KEY 25
# KX 36
# LOC 29
# MX 15
# NAPTR 35
# NS 2 Name Server
# NSEC 47
# NSEC3 50
# NSEC3PARAM 51
# PTR 12 Domain pointer
# RRSIG 46
# RP 17
# SIG 24
# SOA 6 start of authority record
# SPF 99
# SRV 33
# SSHFP 44
# TA 32768
# TKEY 249
# TSIG 250
# TXT 16
# ANY 255
# AXFR 252
# IXFR 251
# OPT 41
DisabledType
# DisabledDomain <DOMAIN1>,<DOMAIN2>,.....
# 禁止查询的域列表,每个域之间用半角逗号 (`,') 分隔 (since 2.2)
# 支持通配符。 (since 2.2.2)
# 一个项目如果不含通配符,则从域名尾部开始匹配,例如 `123.com' 则会匹配所有以 `123.com' 结尾的域名。
# 如果含通配符则严格按照通配符来匹配。
# 可以有多条DisabledDomain (since 2.2.2)
DisabledDomain
# DisabledList <PATH>
# 从文件载入到禁用列表 (since 5.0.3)
# 写多条 `DisabledList' 可以加载多个文件,路径两头不要加引号
DisabledList
# DomainStatistic <BOOLEAN>
# 是否启用域名统计 (since 2.5 b1)
# 域名信息统计会依照模板文件记录域名的查询情况
# 记录的结果在与程序所在相同的文件夹内Windows或程序的配置文件夹内Linux的`statistic.html'文件内
# 可选值:`false' 或 `true'
DomainStatistic false
# DomainStatisticTempletFile <PATH>
# 域名统计的模板文件路径 (since 5.0.23)
# 如果保留为空则默认为与程序所在相同的文件夹内Windows或程序的配置文件夹内Linux的`StatisticTemplate.html'文件
DomainStatisticTempletFile
# StatisticInsertionPosition <STRING>
# 指定在模板文件中写入的位置 (since 5.0.23)
# 如果保留为空,则默认为`<!-- INSERT HERE -->'
# StatisticInsertionPosition <!-- INSERT HERE -->
# StatisticUpdateInterval <NUM>
# 域名统计刷新时间间隔(秒) (since 2.5 b1)
StatisticUpdateInterval 29

View File

@ -1,29 +0,0 @@
#!/bin/sh -e
generate_china_banned()
{
if [ ! -f /tmp/gfwlist.txt ]; then
wget-ssl --no-check-certificate https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt -O /tmp/gfwlist.b64 >&2
cat /tmp/gfwlist.b64 | base64 -d > /tmp/gfwlist.txt
rm -f /tmp/gfwlist.b64
fi
cat /tmp/gfwlist.txt | sort -u |
sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' |
sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /byr\.cn/d; /jlike\.com/d; /weibo\.com/d; /zhongsou\.com/d; /youdao\.com/d; /sogou\.com/d; /so\.com/d; /soso\.com/d; /aliyun\.com/d; /taobao\.com/d; /jd\.com/d; /qq\.com/d' |
sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' |
grep '^[0-9a-zA-Z\.-]\+$' | grep '\.' | sed 's#^\.\+##' | sort -u |
awk '
BEGIN { prev = "________"; } {
cur = $0;
if (index(cur, prev) == 1 && substr(cur, 1 + length(prev) ,1) == ".") {
} else {
print cur;
prev = cur;
}
}' | sort -u
}
generate_china_banned

View File

@ -1,19 +0,0 @@
#!/bin/sh
/etc/dnsforwarder/gen-gfwlist.sh > /tmp/ol-gfw.txt
if [ -s "/tmp/ol-gfw.txt" ];then
sort -u /etc/dnsforwarder/base-gfwlist.txt /tmp/ol-gfw.txt > /tmp/china-banned
if ( ! cmp -s /tmp/china-banned /etc/dnsforwarder/china-banned );then
if [ -s "/tmp/china-banned" ];then
mv /tmp/china-banned /etc/dnsforwarder/china-banned
echo "Update GFW-List Done!"
fi
else
echo "GFW-List No Change!"
fi
fi
rm -f /tmp/gfwlist.txt
rm -f /tmp/ol-gfw.txt

View File

@ -1,2 +0,0 @@
telegram.com
telegram.org

View File

@ -1,2 +0,0 @@
youku.com
iqiyi.com

View File

@ -1,196 +0,0 @@
#!/bin/sh /etc/rc.common
START=99
DNSFORWARDER_CONF=/etc/dnsforwarder/dnsforwarder.conf
PID_PATH=/var/run/dnsforwarder/
PID_FILE=dns.pid
start()
{
echo luci for dnsforwarder
local vt_enabled=`uci get dnsforwarder.@arguments[0].enabled 2>/dev/null`
if [ $vt_enabled = 0 ]; then
echo dnsforwarder is not enabled
exit
fi
dnsforwarder -f $DNSFORWARDER_CONF -d
mkdir -p $PID_PATH
pid=`ps | awk '$5 ~ /\[dnsforwarder\]/ {print $1}'`
echo dnsforwarder running pid is $pid
logger -t alex the pid of dnsforwarder is $PID_PATH/$PID_FILE $pid
echo $pid > $PID_PATH/$PID_FILE
/etc/init.d/dnsforwarder enable
local redir=`uci get dnsforwarder.@arguments[0].redir 2>/dev/null`
local port=`uci get dnsforwarder.@arguments[0].port 2>/dev/null`
local dnsmasq=`uci get dnsforwarder.@arguments[0].dnsmasq 2>/dev/null`
local mode=`uci get dnsforwarder.@arguments[0].mode 2>/dev/null`
local addr=`uci get dnsforwarder.@arguments[0].addr 2>/dev/null`
local ipset=`uci get dnsforwarder.@arguments[0].ipset 2>/dev/null`
local ipset_name=`uci get dnsforwarder.@arguments[0].ipset_name 2>/dev/null`
local white=`uci get dnsforwarder.@arguments[0].white 2>/dev/null`
local whiteset=`uci get dnsforwarder.@arguments[0].whiteset 2>/dev/null`
local whitedns=`uci get dnsforwarder.@arguments[0].whitedns 2>/dev/null`
[ -n "$addr" ] && addr=${addr/:/#}
[ -n "$whitedns" ] && whitedns=${whitedns/:/#}
iptables -t nat -N DNSFORWARDER
iptables -t nat -F DNSFORWARDER
if [ $redir = 1 ]; then
iptables -t nat -A DNSFORWARDER -p udp --dport 53 -j REDIRECT --to-ports $port
iptables -t nat -I PREROUTING -j DNSFORWARDER
fi
mkdir -p /tmp/dnsmasq.d
mkdir -p /etc/dnsmasq.d
cat > /tmp/dnsmasq.d/dnsmasq-go.conf <<EOF
conf-dir=/var/etc/dnsmasq-go.d
EOF
cat > /etc/dnsmasq.d/dnsmasq-go.conf <<EOF
conf-dir=/var/etc/dnsmasq-go.d
EOF
if [ $ipset = 1 ]; then
ipset destroy $ipset_name 2>/dev/null
ipset create $ipset_name hash:net family inet hashsize 1024 maxelem 65536
fi
mkdir -p /var/etc/dnsmasq-go.d
if [ $dnsmasq = 1 ]; then
case $mode in
gfwlist)
echo gfwlist!!
awk -vs=$addr '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/dnsforwarder/china-banned > /var/etc/dnsmasq-go.d/01-pollution.conf
[ $ipset = 1 ] && {
awk '!/^$/&&!/^#/{printf("ipset=/%s/'$ipset_name'\n",$0)}' \
/etc/dnsforwarder/china-banned > /var/etc/dnsmasq-go.d/01-ipset.conf
}
;;
userlist)
echo user!!
awk -vs=$addr '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/dnsforwarder/userlist >> /var/etc/dnsmasq-go.d/02-user.conf
[ $ipset = 1 ] && {
awk '!/^$/&&!/^#/{printf("ipset=/%s/'$ipset_name'\n",$0)}' \
/etc/dnsforwarder/userlist > /var/etc/dnsmasq-go.d/02-ipset.conf
}
;;
gfw_user)
awk -vs=$addr '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/dnsforwarder/china-banned > /var/etc/dnsmasq-go.d/01-pollution.conf
awk -vs=$addr '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/dnsforwarder/userlist >> /var/etc/dnsmasq-go.d/02-user.conf
[ $ipset = 1 ] && {
awk '!/^$/&&!/^#/{printf("ipset=/%s/'$ipset_name'\n",$0)}' \
/etc/dnsforwarder/china-banned > /var/etc/dnsmasq-go.d/01-ipset.conf
awk '!/^$/&&!/^#/{printf("ipset=/%s/'$ipset_name'\n",$0)}' \
/etc/dnsforwarder/userlist > /var/etc/dnsmasq-go.d/02-ipset.conf
}
;;
all)
uci delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server=$addr
uci delete dhcp.@dnsmasq[0].resolvfile
uci set dhcp.@dnsmasq[0].noresolv=1
uci commit dhcp
;;
esac
[ "$mode" = "gfwlist" ] || [ "$mode" = "userlist" ] || [ "$mode" = "gfw_user" ] && {
iptables -t nat -A DNSFORWARDER -p udp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -I PREROUTING -j DNSFORWARDER
}
if [ $white = 1 ]; then
logger -t alex enable white list
echo enable white list
[ -z "$whiteset" ] && whiteset="whiteset"
[ -n "$whitedns" ] && [ -f "/etc/dnsforwarder/whitelist" ] && { #强制不走代理到DNSMasq
echo whiteset is $whiteset
ipset create $whiteset hash:net family inet hashsize 1024 maxelem 65536
awk '!/^$/&&!/^#/{printf("ipset=/%s/'$whiteset'\n",$0)}' \
/etc/dnsforwarder/whitelist > /var/etc/dnsmasq-go.d/03-ipset.conf
awk -vs=$whitedns '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \
/etc/dnsforwarder/whitelist >> /var/etc/dnsmasq-go.d/03-white.conf
}
fi
/etc/init.d/dnsmasq restart
fi
}
stop()
{
logger -t alex stopping dnsforwarder
local addr=`uci get dnsforwarder.@arguments[0].addr 2>/dev/null`
addr=${addr/:/#}
uci del_list dhcp.@dnsmasq[0].server=$addr 2>/dev/null
uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto 2>/dev/null
uci delete dhcp.@dnsmasq[0].noresolv 2>/dev/null
uci commit dhcp
rm -rf /var/etc/dnsmasq-go.d
rm -f /tmp/dnsmasq.d/dnsmasq-go.conf
[ -e $PID_PATH/$PID_FILE ] && {
pid=`cat $PID_PATH/$PID_FILE`
logger -t alex killing dnsforwarder pid $pid
echo killing dnsforwarder pid $pid
kill $pid
rm -f $PID_PATH/$PID_FILE
} || {
logger -t alex cannot find dnsforwarder pid file
}
iptables -t nat -F DNSFORWARDER 2>/dev/null
while iptables -t nat -D PREROUTING -j DNSFORWARDER 2>/dev/null; do :; done
iptables -t nat -X DNSFORWARDER 2>/dev/null
local ipset=`uci get dnsforwarder.@arguments[0].ipset 2>/dev/null`
local ipset_name=`uci get dnsforwarder.@arguments[0].ipset_name 2>/dev/null`
[ $ipset = 1 ] && {
echo destroying ipset $ipset_name
ipset destroy $ipset_name 2>/dev/null
}
local white=`uci get dnsforwarder.@arguments[0].white 2>/dev/null`
local whiteset=`uci get dnsforwarder.@arguments[0].whiteset 2>/dev/null`
[ $white = 1 ] && ipset destroy $whiteset 2>/dev/null
/etc/init.d/dnsmasq restart
}
restart()
{
pid=`cat $PID_PATH/$PID_FILE 2>/dev/null`
echo dnsforwarder pid file is $pid
[ -n "$pid" ] && {
echo stopping pid $pid
logger -t alex there is dnsforwarder pid $pid
stop
} || {
logger -t alex dnsforwarder is not running
}
sleep 1s
local vt_enabled=`uci get dnsforwarder.@arguments[0].enabled 2>/dev/null`
echo dnsforwarder status is $vt_enabled
logger -t alex dnsforwarder is initializing enabled is $vt_enabled
if [ $vt_enabled = 1 ]; then
[ -n "$pid" ] && {
logger -t alex there is dnsforwarder pid $pid
stop
} || {
logger -t alex dnsforwarder is not running
}
logger -t alex restarting dnsforwarder
start
else
/etc/init.d/dnsforwarder disable
fi
}

View File

@ -1,11 +0,0 @@
module("luci.controller.dnsforwarder", package.seeall)
function index()
if not nixio.fs.access("/etc/config/dnsforwarder") then
return
end
entry({"admin", "services", "dnsforwarder"},alias("admin", "services", "dnsforwarder","general"),_("dnsforwarder")).dependent = true
entry({"admin", "services", "dnsforwarder","general"}, cbi("dnsforwarder/general"),_("General"),10).leaf = true
entry({"admin", "services", "dnsforwarder","gfwlist"}, cbi("dnsforwarder/gfwlist"),_("GFWlist"),20).leaf = true
entry({"admin", "services", "dnsforwarder","log"}, cbi("dnsforwarder/log"),_("LOG"),30).leaf = true
end

View File

@ -1,97 +0,0 @@
--Alex<1886090@gmail.com>
local fs = require "nixio.fs"
local CONFIG_FILE = "/etc/dnsforwarder/dnsforwarder.conf";
function sync_value_to_file(value, file)
value = value:gsub("\r\n?", "\n")
local old_value = nixio.fs.readfile(file)
if value ~= old_value then
nixio.fs.writefile(file, value)
end
end
local state_msg = ""
local dnsforwarder_on = (luci.sys.call("pidof dnsforwarder > /dev/null") == 0)
local resolv_file = luci.sys.exec("uci get dhcp.@dnsmasq[0].resolvfile")
local listen_port = luci.sys.exec("uci get dhcp.@dnsmasq[0].server")
if dnsforwarder_on then
state_msg = "<b><font color=\"green\">" .. translate("Running") .. "</font></b>"
else
state_msg = "<b><font color=\"red\">" .. translate("Not running") .. "</font></b>"
end
if dnsforwarder_on and string.sub(listen_port,1,14) == "127.0.0.1#5053" then
state_msg=state_msg .. "DNSmasq已经将流量定向至本软件"
elseif dnsforwarder_on then
state_msg=state_msg .. "<b><font color=\"red\"></font></b>"
end
if resolv_file=="" then
else if dnsforwarder_on then
state_msg=state_msg .. "<b><font color=\"red\"></font></b>"
end
end
m=Map("dnsforwarder",translate("dnsforwarder"),translate("dnsforwarder是企业级DNS服务器可以通过TCP协议进行DNS解析,可以方便的使用iptables进行透明代理配合ipset、GFWList使用效果更佳。默认上游服务器为114DNSSSR和Redsocks的GFWList模式要依赖本软件包提供的功能").. "<br><br>状态 - " .. state_msg)
s=m:section(TypedSection,"arguments","")
s.addremove=false
s.anonymous=true
view_enable = s:option(Flag,"enabled",translate("Enable"))
view_redir = s:option(Flag,"redir",translate("劫持所有DNS请求"),translate("自动将所有客户端的DNS请求都劫持到dnsforwarder的端口"))
view_port = s:option(Value,"port",translate("dnsforwarder监听端口"),translate("请根据下面的配置文件填写端口默认5053"))
view_port:depends({redir=1})
view_port.default="5053"
view_port.datatype="uinteger"
view_dnsmasq = s:option(Flag,"dnsmasq",translate("设置成DNSmasq的上游服务器"),translate("让DNSMasq从本软件获得解析结果支持GFWList模式"))
view_dnsmasq:depends({redir=0})
view_mode=s:option(ListValue,"mode",translate("DNSmasq转发模式"),translate("dnsmasq可以将全部请求发送至本软件也可以只发送GFWList登记部分其余由系统默认DNS解析"))
view_mode:value("gfwlist",translate("只转发GFWList"))
view_mode:value("userlist",translate("只转发用户自定义列表"))
view_mode:value("gfw_user",translate("转发gfwlist+用户自定义列表"))
view_mode:value("all",translate("全部转发给dnsforwarder"))
view_mode:depends({dnsmasq=1})
view_addr = s:option(Value,"addr",translate("转发地址"),translate("请填写dnsforwarder的监听地址,默认127.0.0.1:5053,如果填写<b><font color=\"red\">208.67.222.222:5353</font></b>那么可不通过该软件获得无污染结果"))
view_addr:depends({dnsmasq=1})
view_addr.default = "127.0.0.1:5053"
view_ipset = s:option(Flag,"ipset",translate("将查询结果放入ipset"),translate("为SSRRedsocks的GFWList模式提供依据"))
view_ipset:depends({mode="userlist"})
view_ipset:depends({mode="gfwlist"})
view_ipset:depends({mode="gfw_user"})
view_ipsetname = s:option(Value,"ipset_name",translate("ipset名字"))
view_ipsetname.default = "china-banned"
view_ipsetname:depends({ipset=1})
view_white = s:option(Flag,"white",translate("启用强制不走代理列表"),translate("配合SSR使用设置某些域名不走代理"))
view_white:depends({mode="userlist"})
view_white:depends({mode="gfwlist"})
view_white:depends({mode="gfw_user"})
whitedns = s:option(Value,"whitedns",translate("白名单专用DNS"),translate("白名单内的列表都会用此DNS进行解析并由DNSMasq转发最终不走SSR代理"))
whitedns.default="114.114.114.114:53"
whitedns:depends({white=1})
whiteipset = s:option(Value,"whiteset",translate("白名单ipset"),translate("设置收集到的白名单的域名的ipset列表名字"))
whiteipset:depends({white=1})
whiteipset.default="whiteset"
view_cfg = s:option(TextValue, "1", nil)
view_cfg.rmempty = false
view_cfg.rows = 43
function view_cfg.cfgvalue()
return nixio.fs.readfile(CONFIG_FILE) or ""
end
function view_cfg.write(self, section, value)
sync_value_to_file(value, CONFIG_FILE)
end
-- ---------------------------------------------------
local apply = luci.http.formvalue("cbi.apply")
if apply then
os.execute("/etc/init.d/dnsforwarder restart >/dev/null 2>&1 &")
end
return m

View File

@ -1,69 +0,0 @@
local fs = require "nixio.fs"
local banned = "/etc/dnsforwarder/china-banned"
local user = "/etc/dnsforwarder/userlist"
local whitedomin = "/etc/dnsforwarder/whitelist"
function sync_value_to_file(value, file)
value = value:gsub("\r\n?", "\n")
local old_value = nixio.fs.readfile(file)
if value ~= old_value then
nixio.fs.writefile(file, value)
end
end
m = Map("dnsforwarder", translate("Domain Lists Settings"),translate("GFWList黑名单可以观察当前域名黑名单更新后会发生变化;<br>用户自定义黑名单不会被GFWList更新所覆盖可以手动添加一些强制走代理的网站。<br>注意:点击更新按钮后需要等浏览器自动刷新后才算完成,请勿重复点击"))
s=m:section(TypedSection,"arguments","")
s.addremove=false
s.anonymous=true
button_update_gfwlist = s:option (Button, "_button_update_gfwlist", translate("更新GFWList"),translate("点击后请静待30秒,然后刷新本页面"))
local gfw_count = luci.sys.exec("grep -c '' " .. banned)
button_update_gfwlist.inputtitle = translate ( "当前规则数目" .. gfw_count .. ",点击更新")
button_update_gfwlist.inputstyle = "apply"
function button_update_gfwlist.write (self, section, value)
luci.sys.call("nohup sh /etc/dnsforwarder/up-gfwlist.sh > /tmp/gfwupdate.log 2>&1 &")
end
gfwlist = s:option(TextValue, "gfwlist", translate("被GFW屏蔽的名单"), nil)
gfwlist.description = translate("该列表内的内容会随着GFWList更新而覆盖")
gfwlist.rows = 13
gfwlist.wrap = "off"
gfwlist.cfgvalue = function(self, section)
return fs.readfile(banned) or ""
end
gfwlist.write = function(self, section, value)
fs.writefile(banned, value:gsub("\r\n", "\n"))
end
userlist = s:option(TextValue, "users", translate("用户自定义黑名单"), nil)
userlist.description = translate("该列表的内容不会随着GFWList的更新而改变")
userlist.rows = 13
userlist.wrap = "off"
userlist.cfgvalue = function(self, section)
return fs.readfile(user) or ""
end
userlist.write = function(self, section, value)
fs.writefile(user, value:gsub("\r\n", "\n"))
end
goods = s:option(TextValue, "fafa", translate("强制不走代理白名单"), nil)
goods.description = translate("一般填写国内的CDN服务器地址需配合SSR的GFWList自动代理模式使用")
goods.rows = 13
goods.wrap = "off"
goods.cfgvalue = function(self, section)
return fs.readfile(whitedomin) or ""
end
goods.write = function(self, section, value)
fs.writefile(whitedomin, value:gsub("\r\n", "\n"))
end
-- ---------------------------------------------------
local apply = luci.http.formvalue("cbi.apply")
if apply then
os.execute("/etc/init.d/dnsforwarder restart >/dev/null 2>&1 &")
end
return m

View File

@ -1,31 +0,0 @@
local fs = require "nixio.fs"
local log = "/var/log/dnsforwarder.log"
function sync_value_to_file(value, file)
value = value:gsub("\r\n?", "\n")
local old_value = nixio.fs.readfile(file)
if value ~= old_value then
nixio.fs.writefile(file, value)
end
end
m = Map("dnsforwarder", translate("运行日志"),translate("如果想观察日志需要在配置文件中写明LogOn true 和 LogFileFolder /var/log"))
s=m:section(TypedSection,"arguments","")
s.addremove=false
s.anonymous=true
gfwlist = s:option(TextValue, "gfwlist", translate("日志"), nil)
gfwlist.description = translate("-------------------------------------------------------------日志文件默认位置:" .. log)
gfwlist.rows = 30
gfwlist.wrap = "off"
gfwlist.cfgvalue = function(self, section)
return fs.readfile(log) or ""
end
return m

View File

@ -1,8 +0,0 @@
msgid "Enable"
msgstr "启用"
msgid "Running"
msgstr "运行中"
msgid "Not running"
msgstr "未运行"

View File

@ -1,12 +0,0 @@
INSTALL = install
PREFIX = /usr/bin
po2lmo: src/po2lmo.o src/template_lmo.o
$(CC) $(LDFLAGS) -o src/po2lmo src/po2lmo.o src/template_lmo.o
install:
$(INSTALL) -m 755 src/po2lmo $(PREFIX)
clean:
$(RM) src/po2lmo src/*.o

View File

@ -1,247 +0,0 @@
/*
* lmo - Lua Machine Objects - PO to LMO conversion tool
*
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "template_lmo.h"
static void die(const char *msg)
{
fprintf(stderr, "Error: %s\n", msg);
exit(1);
}
static void usage(const char *name)
{
fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
exit(1);
}
static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if( fwrite(ptr, size, nmemb, stream) == 0 )
die("Failed to write stdout");
}
static int extract_string(const char *src, char *dest, int len)
{
int pos = 0;
int esc = 0;
int off = -1;
for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
{
if( (off == -1) && (src[pos] == '"') )
{
off = pos + 1;
}
else if( off >= 0 )
{
if( esc == 1 )
{
switch (src[pos])
{
case '"':
case '\\':
off++;
break;
}
dest[pos-off] = src[pos];
esc = 0;
}
else if( src[pos] == '\\' )
{
dest[pos-off] = src[pos];
esc = 1;
}
else if( src[pos] != '"' )
{
dest[pos-off] = src[pos];
}
else
{
dest[pos-off] = '\0';
break;
}
}
}
return (off > -1) ? strlen(dest) : -1;
}
static int cmp_index(const void *a, const void *b)
{
uint32_t x = ((const lmo_entry_t *)a)->key_id;
uint32_t y = ((const lmo_entry_t *)b)->key_id;
if (x < y)
return -1;
else if (x > y)
return 1;
return 0;
}
static void print_uint32(uint32_t x, FILE *out)
{
uint32_t y = htonl(x);
print(&y, sizeof(uint32_t), 1, out);
}
static void print_index(void *array, int n, FILE *out)
{
lmo_entry_t *e;
qsort(array, n, sizeof(*e), cmp_index);
for (e = array; n > 0; n--, e++)
{
print_uint32(e->key_id, out);
print_uint32(e->val_id, out);
print_uint32(e->offset, out);
print_uint32(e->length, out);
}
}
int main(int argc, char *argv[])
{
char line[4096];
char key[4096];
char val[4096];
char tmp[4096];
int state = 0;
int offset = 0;
int length = 0;
int n_entries = 0;
void *array = NULL;
lmo_entry_t *entry = NULL;
uint32_t key_id, val_id;
FILE *in;
FILE *out;
if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
usage(argv[0]);
memset(line, 0, sizeof(key));
memset(key, 0, sizeof(val));
memset(val, 0, sizeof(val));
while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
{
if( state == 0 && strstr(line, "msgid \"") == line )
{
switch(extract_string(line, key, sizeof(key)))
{
case -1:
die("Syntax error in msgid");
case 0:
state = 1;
break;
default:
state = 2;
}
}
else if( state == 1 || state == 2 )
{
if( strstr(line, "msgstr \"") == line || state == 2 )
{
switch(extract_string(line, val, sizeof(val)))
{
case -1:
state = 4;
break;
default:
state = 3;
}
}
else
{
switch(extract_string(line, tmp, sizeof(tmp)))
{
case -1:
state = 2;
break;
default:
strcat(key, tmp);
}
}
}
else if( state == 3 )
{
switch(extract_string(line, tmp, sizeof(tmp)))
{
case -1:
state = 4;
break;
default:
strcat(val, tmp);
}
}
if( state == 4 )
{
if( strlen(key) > 0 && strlen(val) > 0 )
{
key_id = sfh_hash(key, strlen(key));
val_id = sfh_hash(val, strlen(val));
if( key_id != val_id )
{
n_entries++;
array = realloc(array, n_entries * sizeof(lmo_entry_t));
entry = (lmo_entry_t *)array + n_entries - 1;
if (!array)
die("Out of memory");
entry->key_id = key_id;
entry->val_id = val_id;
entry->offset = offset;
entry->length = strlen(val);
length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
print(val, length, 1, out);
offset += length;
}
}
state = 0;
memset(key, 0, sizeof(key));
memset(val, 0, sizeof(val));
}
memset(line, 0, sizeof(line));
}
print_index(array, n_entries, out);
if( offset > 0 )
{
print_uint32(offset, out);
fsync(fileno(out));
fclose(out);
}
else
{
fclose(out);
unlink(argv[2]);
}
fclose(in);
return(0);
}

View File

@ -1,328 +0,0 @@
/*
* lmo - Lua Machine Objects - Base functions
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "template_lmo.h"
/*
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
* Copyright (C) 2004-2008 by Paul Hsieh
*/
uint32_t sfh_hash(const char *data, int len)
{
uint32_t hash = len, tmp;
int rem;
if (len <= 0 || data == NULL) return 0;
rem = len & 3;
len >>= 2;
/* Main loop */
for (;len > 0; len--) {
hash += sfh_get16(data);
tmp = (sfh_get16(data+2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2*sizeof(uint16_t);
hash += hash >> 11;
}
/* Handle end cases */
switch (rem) {
case 3: hash += sfh_get16(data);
hash ^= hash << 16;
hash ^= data[sizeof(uint16_t)] << 18;
hash += hash >> 11;
break;
case 2: hash += sfh_get16(data);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1: hash += *data;
hash ^= hash << 10;
hash += hash >> 1;
}
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}
uint32_t lmo_canon_hash(const char *str, int len)
{
char res[4096];
char *ptr, prev;
int off;
if (!str || len >= sizeof(res))
return 0;
for (prev = ' ', ptr = res, off = 0; off < len; prev = *str, off++, str++)
{
if (isspace(*str))
{
if (!isspace(prev))
*ptr++ = ' ';
}
else
{
*ptr++ = *str;
}
}
if ((ptr > res) && isspace(*(ptr-1)))
ptr--;
return sfh_hash(res, ptr - res);
}
lmo_archive_t * lmo_open(const char *file)
{
int in = -1;
uint32_t idx_offset = 0;
struct stat s;
lmo_archive_t *ar = NULL;
if (stat(file, &s) == -1)
goto err;
if ((in = open(file, O_RDONLY)) == -1)
goto err;
if ((ar = (lmo_archive_t *)malloc(sizeof(*ar))) != NULL)
{
memset(ar, 0, sizeof(*ar));
ar->fd = in;
ar->size = s.st_size;
fcntl(ar->fd, F_SETFD, fcntl(ar->fd, F_GETFD) | FD_CLOEXEC);
if ((ar->mmap = mmap(NULL, ar->size, PROT_READ, MAP_SHARED, ar->fd, 0)) == MAP_FAILED)
goto err;
idx_offset = ntohl(*((const uint32_t *)
(ar->mmap + ar->size - sizeof(uint32_t))));
if (idx_offset >= ar->size)
goto err;
ar->index = (lmo_entry_t *)(ar->mmap + idx_offset);
ar->length = (ar->size - idx_offset - sizeof(uint32_t)) / sizeof(lmo_entry_t);
ar->end = ar->mmap + ar->size;
return ar;
}
err:
if (in > -1)
close(in);
if (ar != NULL)
{
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
munmap(ar->mmap, ar->size);
free(ar);
}
return NULL;
}
void lmo_close(lmo_archive_t *ar)
{
if (ar != NULL)
{
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
munmap(ar->mmap, ar->size);
close(ar->fd);
free(ar);
ar = NULL;
}
}
lmo_catalog_t *_lmo_catalogs = NULL;
lmo_catalog_t *_lmo_active_catalog = NULL;
int lmo_load_catalog(const char *lang, const char *dir)
{
DIR *dh = NULL;
char pattern[16];
char path[PATH_MAX];
struct dirent *de = NULL;
lmo_archive_t *ar = NULL;
lmo_catalog_t *cat = NULL;
if (!lmo_change_catalog(lang))
return 0;
if (!dir || !(dh = opendir(dir)))
goto err;
if (!(cat = malloc(sizeof(*cat))))
goto err;
memset(cat, 0, sizeof(*cat));
snprintf(cat->lang, sizeof(cat->lang), "%s", lang);
snprintf(pattern, sizeof(pattern), "*.%s.lmo", lang);
while ((de = readdir(dh)) != NULL)
{
if (!fnmatch(pattern, de->d_name, 0))
{
snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
ar = lmo_open(path);
if (ar)
{
ar->next = cat->archives;
cat->archives = ar;
}
}
}
closedir(dh);
cat->next = _lmo_catalogs;
_lmo_catalogs = cat;
if (!_lmo_active_catalog)
_lmo_active_catalog = cat;
return 0;
err:
if (dh) closedir(dh);
if (cat) free(cat);
return -1;
}
int lmo_change_catalog(const char *lang)
{
lmo_catalog_t *cat;
for (cat = _lmo_catalogs; cat; cat = cat->next)
{
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
{
_lmo_active_catalog = cat;
return 0;
}
}
return -1;
}
static lmo_entry_t * lmo_find_entry(lmo_archive_t *ar, uint32_t hash)
{
unsigned int m, l, r;
uint32_t k;
l = 0;
r = ar->length - 1;
while (1)
{
m = l + ((r - l) / 2);
if (r < l)
break;
k = ntohl(ar->index[m].key_id);
if (k == hash)
return &ar->index[m];
if (k > hash)
{
if (!m)
break;
r = m - 1;
}
else
{
l = m + 1;
}
}
return NULL;
}
int lmo_translate(const char *key, int keylen, char **out, int *outlen)
{
uint32_t hash;
lmo_entry_t *e;
lmo_archive_t *ar;
if (!key || !_lmo_active_catalog)
return -2;
hash = lmo_canon_hash(key, keylen);
for (ar = _lmo_active_catalog->archives; ar; ar = ar->next)
{
if ((e = lmo_find_entry(ar, hash)) != NULL)
{
*out = ar->mmap + ntohl(e->offset);
*outlen = ntohl(e->length);
return 0;
}
}
return -1;
}
void lmo_close_catalog(const char *lang)
{
lmo_archive_t *ar, *next;
lmo_catalog_t *cat, *prev;
for (prev = NULL, cat = _lmo_catalogs; cat; prev = cat, cat = cat->next)
{
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
{
if (prev)
prev->next = cat->next;
else
_lmo_catalogs = cat->next;
for (ar = cat->archives; ar; ar = next)
{
next = ar->next;
lmo_close(ar);
}
free(cat);
break;
}
}
}

View File

@ -1,92 +0,0 @@
/*
* lmo - Lua Machine Objects - General header
*
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _TEMPLATE_LMO_H_
#define _TEMPLATE_LMO_H_
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <fnmatch.h>
#include <dirent.h>
#include <ctype.h>
#include <limits.h>
#if (defined(__GNUC__) && defined(__i386__))
#define sfh_get16(d) (*((const uint16_t *) (d)))
#else
#define sfh_get16(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
struct lmo_entry {
uint32_t key_id;
uint32_t val_id;
uint32_t offset;
uint32_t length;
} __attribute__((packed));
typedef struct lmo_entry lmo_entry_t;
struct lmo_archive {
int fd;
int length;
uint32_t size;
lmo_entry_t *index;
char *mmap;
char *end;
struct lmo_archive *next;
};
typedef struct lmo_archive lmo_archive_t;
struct lmo_catalog {
char lang[6];
struct lmo_archive *archives;
struct lmo_catalog *next;
};
typedef struct lmo_catalog lmo_catalog_t;
uint32_t sfh_hash(const char *data, int len);
uint32_t lmo_canon_hash(const char *data, int len);
lmo_archive_t * lmo_open(const char *file);
void lmo_close(lmo_archive_t *ar);
extern lmo_catalog_t *_lmo_catalogs;
extern lmo_catalog_t *_lmo_active_catalog;
int lmo_load_catalog(const char *lang, const char *dir);
int lmo_change_catalog(const char *lang);
int lmo_translate(const char *key, int keylen, char **out, int *outlen);
void lmo_close_catalog(const char *lang);
#endif