update 2026-05-10 09:48:30

This commit is contained in:
action
2026-05-10 09:48:30 +08:00
parent 95ac96413e
commit 0b362674f1
6244 changed files with 2992248 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=appfilter
PKG_VERSION:=6.1.8
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
TARGET_CFLAGS +=-Werror=implicit-function-declaration
define Package/appfilter
SECTION:=TT Apps
CATEGORY:=TT Apps
DEPENDS:=+libubox +libubus +libuci +libpthread +libjson-c +libblobmsg-json
TITLE:=OAF client and config service
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
cp -rf ./src/* $(PKG_BUILD_DIR)
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/ \
CC="$(TARGET_CROSS)gcc" \
CFLAGS="$(TARGET_CFLAGS)" \
LIBS="$(TARGET_LDFLAGS) -lm -lpthread -lubox -luci -lubus -ljson-c -lblobmsg_json" \
all
endef
define Build/Compile/Default
endef
define Package/appfilter/description
openappfilter app
endef
define Package/appfilter/conffiles
/etc/config/appfilter
/etc/config/user_info
endef
define Package/appfilter/install
$(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d
$(INSTALL_DIR) $(1)/etc/appfilter
$(INSTALL_DIR) $(1)/etc/config
$(CP) ./files/*.cfg $(1)/etc/appfilter/
$(INSTALL_BIN) ./files/appfilter.init $(1)/etc/init.d/appfilter
$(INSTALL_BIN) ./files/oaf_rule $(1)/usr/bin
$(INSTALL_BIN) ./files/gen_class.sh $(1)/usr/bin
$(INSTALL_DATA) ./files/appfilter.config $(1)/etc/config/appfilter
$(INSTALL_DATA) ./files/user_info.config $(1)/etc/config/user_info
$(INSTALL_BIN) $(PKG_BUILD_DIR)/oafd $(1)/usr/bin
$(INSTALL_BIN) ./files/hnat.sh $(1)/usr/bin
endef
$(eval $(call BuildPackage,appfilter))
+36
View File
@@ -0,0 +1,36 @@
config global global
option enable '0'
option work_mode '0'
option record_enable '1'
option disable_hnat '0'
option tcp_rst '1'
option lan_ifname 'br-lan'
option auto_load_engine '1'
option disable_quic '0'
config appfilter appfilter
config feature feature
option update 0
option format 'v3.0'
config time 'time'
option deny_time '60'
option start_time '00:00'
option end_time '23:59'
option allow_time '20'
option time_mode '0'
option days '1 2 3 4 5 6 0'
list time '00:00-23:59'
option daily_limit_0 '0:0:0'
option daily_limit_1 '0:0:0'
option daily_limit_2 '0:0:0'
option daily_limit_3 '0:0:0'
option daily_limit_4 '0:0:0'
option daily_limit_5 '0:0:0'
option daily_limit_6 '0:0:0'
config user user
config rule 'rule'
+27
View File
@@ -0,0 +1,27 @@
#!/bin/sh /etc/rc.common
START=96
USE_PROCD=1
OAFD_BIN="/usr/bin/oafd"
FEATURE_FILE="/tmp/feature.cfg"
stop_service(){
killall -9 oafd
}
start_service(){
test -f $FEATURE_FILE &&{
rm $FEATURE_FILE
}
if [ ! -f /etc/appfilter/feature.cfg ]; then
cp /etc/appfilter/feature_cn.cfg /etc/appfilter/feature.cfg
fi
hnat.sh 1
ln -s /etc/appfilter/feature.cfg $FEATURE_FILE
procd_open_instance
procd_set_param respawn 60 5 5
procd_set_param stderr 1
procd_set_param command "$OAFD_BIN"
procd_close_instance
}
+256
View File
@@ -0,0 +1,256 @@
#version v22.3.24
#format v3.0
#id name:[proto;sport;dport;host url;request;dict]
#class chat 1 聊天
1003 微博:[tcp;;;weibo;;]
1004 陌陌:[tcp;;;momo;;,tcp;;;;;04:2f|05:66|06:65|07:65;;1,tcp;;;;;00:03|01:03|02:00;;1]
1005 支付宝:[tcp;;;alipay.com;;,tcp;;;alipayobjects.com;;,tcp;;;alive.alipay.com;;,udp;;1100-1200;;;00:00|01:01|02:00,tcp;;80;;;00:50|01:52|02:49]
1006 钉钉:[tcp;;;dingtalk;;,tcp;;;;d?host=;,tcp;;;;/man/api;]
1007 Soul:[tcp;;;soulapp;;]
1008 伊对:[tcp;;;520yidui;;]
1009 探探:[tcp;;;tancdn;;,tcp;;;tantanapp;;]
1010 多闪:[tcp;;;ppkankan;;]
1012 Instagram:[tcp;;;instagram;;]
1013 Facebook:[tcp;;;facebook;;]
1014 WhatsApp:[tcp;;;whatsapp;;]
#class game 2 游戏
2001 王者荣耀:[tcp;;6000-9000;;;00:33|1:66|02:00|03:0a]
2027 英雄联盟手游:[tcp;;10001;;;00:33|1:66|02:00|03:0b,tcp;;11001;;;00:33|1:66|02:00|03:0b]
2005 欢乐斗地主:[tcp;;12000;;;00:43|01:66|02:aa|03:00,tcp;;;huanle.qq.com;;]
2015 我的世界:[tcp;;443;g79mclobt.nie.netease;;,tcp;;443;x19.*.netease.com;;,tcp;;443;mc.*.netease;;]
2006 梦幻西游:[tcp;;;;;00:0e|01:00|02:fe|03:ff,tcp;;;g18.proxima.nie;;]
2007 明日之后:[tcp;;12500-14000;;;00:02|01:00|02:00|03:00|04:00|05:00,tcp;;;g66.update.netease;;]
2008 QQ飞车:[udp;;;;;00:28|01:28,tcp;;10000;;;00:33|01:66|02:00|03:08]
2009 跑跑卡丁车:[tcp;;8888;;;00:33|01:66|02:00|03:0b,tcp;;49150-49159;;wepop/;]
2010 开心消消乐:[tcp;;80;happyelements;;]
2011 狂野飙车:[tcp;;;asphalt9;;]
2012 率土之滨:[tcp;;10001;;;00:00|01:00,tcp;;8001;;;00:00|01:00]
2013 一刀传世:[tcp;;8040;;;00:47|01:45]
2014 第五人格:[tcp;;;h55.proxima;;,tcp;;;h55.update;;]
2016 皇室战争:[udp;;9339;;;]
2017 炉石传说:[tcp;;3724;;;00:73:01:00:02:00]
2023 原神:[tcp;;443;yuanshen.com;;]
2025 天涯明月刀:[tcp;;10000;;;00:43|01:66|02:aa]
2026 微信小游戏:[tcp;;443;mmgame;;,tcp;;443;game.weixin.qq;;]
2033 我叫MT4:[tcp;;21248;;;,tcp;;;dir.mt4.qq.com;;]
2034 神都夜行录:[udp;;;;;00:00|01:00|02:00|03:00|04:56|05:40]
2041 光遇:[udp;;10000-15000;;;00:8f|01:ff,tcp;;;ma75.update.netease.com;;,tcp;;;ma75.proxima.nie.netease;;]
2042 保卫萝卜4:[tcp;;;s4.luobo.cn;;]
2040 哈利波特:[tcp;;10021-12000;;;00:02|01:00|02:00|03:00|04:00|05:00,tcp;;443;g92.proxima;;]
2067 9377游戏:[tcp;;;www.9377.com;;]
2068 4399游戏:[tcp;;;4399.com;;]
2069 7k7k游戏:[tcp;;;7k7k.com;;]
2070 17173游戏:[tcp;;;17173.com;;]
2071 37网游:[tcp;;;37.com;;]
2074 hao123游戏:[tcp;;;game.hao123.com;;]
2075 51游戏:[tcp;;;www.51.com;;]
2050 uu加速器:[tcp;;;mg.uu.163.com;;]
2051 腾讯加速器:[tcp;;;m.acc.qq.com;;]
2080 乐逗游戏:[tcp;;;.uu.cc;;]
#class video 3 视频
3001 抖音:[tcp;;;-dy-;;,tcp;;;-dy.;;,tcp;;;douyin;;,tcp;;;amemv.com;;,tcp;;;pstatp.com;;,tcp;;;volcsirius.com;;,tcp;;80;;^/pull.*.douyincdn.com;,tcp;;;ecombdapi.com;;,udp;;443;;;09:51|10:30|11:34;amemv.com;0,udp;;16000;;;00:00|01:01,udp;;1000-2000;;;00:00|01:01]
3049 Youtube:[tcp;;;youtube;;]
3006 斗鱼:[tcp;;;douyu;;,tcp;;;douyu;;-2:2f|-1:00]
3004 爱奇艺:[tcp;;;iqiyi;;,tcp;;;qy.net;;,tcp;;;inter.71edge.com;;,tcp;;;;^/videos;,tcp;;80;;;00:51|01:48|02:54,tcp;;80;;;09:00|10:00|11:00]
3043 Netflix:[tcp;;;netflix.com;;]
3008 虎牙直播:[tcp;;;huya;;,udp;;;;;01:00|02:00|03:00|04:23,udp;;;;;01:00|02:00|03:00|04:24]
3010 小红书:[tcp;;;xiaohongshu;;,tcp;;;xhscdn;;]
3011 花椒直播:[tcp;;;huajiao;;]
3012 映客直播:[tcp;;;;.inke.cn;]
3016 芒果tv:[tcp;;443;mgtv;;,tcp;;80;mgtv;;,tcp;;443;hitv;;]
3017 西瓜视频:[tcp;;;ixigua;;,tcp;;443;snsdk;;,tcp;;;xg-p.ixigua;;,tcp;;;bdxigua;;]
3018 搜狐视频:[tcp;;;aty.sohu.com;;,tcp;;;tv.itc.cn;;]
3020 咪咕视频:[tcp;;;miguvideo;;,tcp;;;migu.cn;;]
3022 人人视频:[tcp;;;rr.tv;;]
3023 央视影音:[tcp;;;cntv;;]
3024 优酷&酷喵:[tcp;;;youku;;,tcp;;;ykimg;;,tcp;;;;/youku;,tcp;;;galitv.alicdn.com;;,tcp;;;cibntv.;;,tcp;;;miaozhen.com;;;;1]
3025 最右:[tcp;;;izuiyou;;]
3026 风行视频:[tcp;;;funshion;;]
3019 播聊:[tcp;;80;randlove.cn;;,tcp;;;yueliao;;,tcp;;;5glive;;]
3021 韩剧TV:[tcp;;;hanju.koudaibaobao;;]
3027 企鹅电竞:[tcp;;;egame.qq;;,tcp;;;liveplay;;,tcp;;;;pggame;]
3028 波波视频:[tcp;;;miaopai;;]
3029 酷狗短酷:[tcp;;;bssdl.kugou;;]
3030 酷狗直播:[tcp;;;rt-m.kugou;;,tcp;;;kgimg.com;;]
3023 央视影音:[tcp;;;cntv;;]
3026 风行视频:[tcp;;;funshion;;]
3089 华数TV:[tcp;;;wasu.cn;;]
3121 梨视频:[tcp;;;pearvideo.com;;]
3094 南瓜电影:[tcp;;;vcinema.cn;;]
3084 六间房:[tcp;;;v.6.cn;;]
3085 百度直播:[tcp;;;live.baidu.com;;]
3086 度小视:[tcp;;;quanmin.baidu.com;;]
#class shopping 4 购物
4001 淘宝:[tcp;;;taobao;;,tcp;;;alicdn.com;;,tcp;;;tmall.com;;,tcp;;443;;;00:d1|01:00,tcp;;443;;;00:d2|01:00,tcp;;443;;;00:d3|01:00,tcp;;443;;;00:d4|01:00,tcp;;443;;;00:d5|01:00,tcp;;443;;;00:b1|01:00,tcp;;443;;;00:b2|01:00,tcp;;443;;;00:b3|01:00,tcp;;443;;;00:b4|01:00,tcp;;443;;;00:b5|01:00,udp;;1000-1200;;;00:82|01:cc,tcp;;;;/mediaplatform;]
4002 京东:[tcp;;;360buyimg;;,tcp;;;jd.com;;,tcp;;;jdcdn.com;;,tcp;;;vod.300hu.com;;]
4003 唯品会:[tcp;;;vips-mobile;;,tcp;;;vipshop;;,tcp;;;vip.com;;,tcp;;;vipstatic.com;;,tcp;;;appsimg.com;;]
4004 拼多多:[tcp;;;pinduoduo;;,tcp;;;yangkeduo.com;;,tcp;;;s1p.cdntip.com;;]
4010 饿了么:[tcp;;;eleme;;]
4012 闲鱼:[tcp;;;xianyu;;]
4021 转转:[tcp;;;zhuanzhuan;;,tcp;;;zhuanstatic;;]
4005 蘑菇街:[tcp;;;mogujie;;,tcp;;;mogucdn;;,tcp;;;;;00:73|01:ea|02:68|03:fb|04:3f]
4006 苏宁易购:[tcp;;;.suning.;;]
4007 当当网:[tcp;;;.dangdang.com;;]
4008 1号店:[tcp;;;.yhd.com;;]
4009 朴朴超市:[tcp;;;pupumall;;,tcp;;;pupuapi;;]
4013 叮咚买菜:[tcp;;;ddxq.mobi;;]
4014 小米有品:[tcp;;;youpin;;,tcp;;;shopapi.io.mi.com;;]
4015 微店:[tcp;;;weidian;;]
4016 折800:[tcp;;;zhe800.com;;]
4018 好省:[tcp;;;hzhstb.com;;]
4019 什么值得买:[tcp;;;smzdm.com;;]
4022 网易严选:[tcp;;;yanxuan;;]
4023 识货:[tcp;;;shihuo;;]
4024 考拉海购:[tcp;;;kaola;;]
4025 宜家家居:[tcp;;;ikea.cn;;]
4026 小象优品:[tcp;;;xiaoxiangyoupin;;]
4040 国美:[tcp;;;gome.com;;]
4041 酒仙网:[tcp;;;jiuxian.com;;]
4052 1688:[tcp;;;1688.com;;]
4053 亚马逊:[tcp;;;amazon.cn;;]
4054 Lazada:[tcp;;;lazada.com;;]
#class music 5 音乐
5001 网易云音乐:[tcp;;;music.163;;,tcp;;;music.126;;]
5002 QQ音乐:[tcp;;;;^/amobile.music.tc.qq.com;,tcp;;;qqmusic;;]
5003 酷狗音乐:[tcp;;;kugou;;,tcp;;;kgimg;;,tcp;;;fanxing;;]
5004 酷我音乐:[tcp;;;.kuwo.cn;;]
5005 喜马拉雅:[tcp;;;.ximalaya.com;;]
5006 千千音乐:[tcp;;;music.taihe.com;;]
5007 虾米音乐:[tcp;;;xiami;;]
5008 音悦台:[tcp;;;yinyuetai.com;;]
5009 豆瓣FM:[tcp;;;douban.fm;;]
5010 唱吧:[tcp;;;changba.com;;]
5011 音乐随心听:[tcp;;;fm.taihe.com;;]
5012 懒人听书:[tcp;;;lrts.me;;]
#class employee 6 招聘
6001 前程无忧:[tcp;;;51job;;]
6002 智联招聘:[tcp;;;zhaopin;;]
6003 猎聘:[tcp;;;liepin;;]
6004 赶集网:[tcp;;;58.com;;,tcp;;;58cdn;;]
6005 同城急聘:[tcp;;;xiaomei;;]
6006 领英:[tcp;;;linkedin;;]
6007 斗米:[tcp;;;doumi;;]
6008 看准:[tcp;;;kanzhun.com;;]
6009 应届生求职:[tcp;;;yingjiesheng.com;;]
6010 中华英才网:[tcp;;;chinahr.com;;]
6011 拉勾网:[tcp;;;lagou.com;;]
6012 大街网:[tcp;;;dajie.com;;]
6013 boss直聘:[tcp;;;zhipin.com;;]
6014 实习僧:[tcp;;;shixiseng.com;;]
#class download 7 下载
7002 AppStore:[tcp;;;itunes.apple.com;;]
7004 ftp文件传输:[tcp;;21;;;]
7005 vivo应用商店:[tcp;;443;appstore.vivo;;,tcp;;443;apkappdefwsdl.vivo;;]
7006 王者荣耀更新:[tcp;;80;;/sgame/;]
7007 天翼云盘:[tcp;;;ctyunapi;;]
7008 腾讯微云:[tcp;;;weiyun.com;;,tcp;;;aegis.qq.com;;,tcp;;;pingtas.qq.com;;,tcp;;443;;;00:77|01:6e|02:73]
7009 坚果云:[tcp;;;jianguoyun;;]
7010 蓝奏云:[tcp;;;pan.lanzou.com;;]
7011 华为云:[tcp;;;cloud.huawei.com;;,tcp;;;hicloud.com;;,tcp;;;myhuaweicloud.cn;;]
7020 windows更新:[tcp;;80;update.microsoft.com;;,tcp;;;windowsupdate.com;;]
7030 向日葵:[tcp;;;oray.com;;,tcp;;;oray.net;;]
7031 TeamViewer:[tcp;;;teamviewer;;]
7032 阿里云盘:[tcp;;;aliyundrive;;]
#class website 8 常用网站
8079 Google:[tcp;;;google.com;;]
8001 百度:[tcp;;;www.baidu.com;;,tcp;;;m.baidu.com;;]
8112 Apple:[tcp;;;www.apple.com;;,tcp;;;m.apple.com;;]
8002 新浪:[tcp;;;www.sina.com;;,tcp;;;m.sina.com;;]
8003 搜狐:[tcp;;;www.sohu.com;;,tcp;;;m.sohu.com;;]
8004 网易:[tcp;;;www.163.com;;,tcp;;443;www.126.com;;]
8005 凤凰网:[tcp;;;ifeng.com;;]
8009 hao123:[tcp;;;www.hao123.com;;,tcp;;;m.hao123.com;;]
8010 2345:[tcp;;;www.2345.com;;,tcp;;;m.2345.com;;]
8006 人民网:[tcp;;;people.com.cn;;]
8008 中华网:[tcp;;;www.china.com;;]
8020 天涯社区:[tcp;;;tianya.cn;;]
8026 穷游网:[tcp;;;qyer.com;;]
8027 驴妈妈:[tcp;;;lvmama.com;;]
8029 太平洋汽车:[tcp;;;pcauto.com.cn;;]
8030 易车网:[tcp;;;bitauto.com;;]
8031 爱卡汽车:[tcp;;;xcar.com.cn;;]
8035 和讯:[tcp;;;hexun.com;;]
8036 第一财经:[tcp;;;yicai.com;;]
8037 全景网:[tcp;;;p5w.net;;]
8038 中彩网:[tcp;;;zhcw.com;;]
8039 体育彩票:[tcp;;;lottery.gov.cn;;]
8041 豆丁:[tcp;;;docin.com;;]
8044 缤客:[tcp;;;booking.com;;]
8046 猫扑:[tcp;;;mop.com;;]
8064 潇湘书院:[tcp;;;xxsy.net;;]
8065 cctv5:[tcp;;;sports.cctv.com;;]
8066 虎扑体育:[tcp;;;hupu.com;;]
8077 知网:[tcp;;;www.cnki.net;;]
8087 github:[tcp;;;github.com;;]
8089 gitee:[tcp;;;gitee.com;;]
8090 必应:[tcp;;;bing.com;;]
8092 中国福利彩:[tcp;;;www.cwl.gov.cn;;]
8093 新浪彩票:[tcp;;;lottery.sina.com.cn;;]
8094 竞彩网:[tcp;;;www.sporttery.cn;;]
8096 新浪体育:[tcp;;;sports.sina.com.cn;;]
8098 小米官网:[tcp;;;www.mi.com;;]
8099 BBC:[tcp;;;www.bbc.com;;]
8100 腾讯智影:[tcp;;;zenvideo.qq.com;;]
8103 IT之家:[tcp;;;www.ithome.com;;]
8104 太平洋电脑:[tcp;;;www.pconline.com.cn;;]
8105 中国移动:[tcp;;;www.10086.cn;;]
8106 中国联通:[tcp;;;www.10010.com;;]
8107 中国电信:[tcp;;;www.189.cn;;]
8108 华为商城:[tcp;;;www.vmall.com;;]
8110 vivo官网:[tcp;;;www.vivo.com.cn;;]
8111 华为官网:[tcp;;;www.huawei.com;;]
#class life 10 生活
10003 京东钱包:[tcp;;;jdpay.com;;]
10034 饿了么:[tcp;;;eleme.com;;]
10035 美团:[tcp;;;meituan;;]
10004 豆瓣:[tcp;;;douban.com;;]
10005 知乎:[tcp;;;zhihu.com;;]
10006 链家:[tcp;;;lianjia.com;;]
10007 天眼查:[tcp;;;tianyancha.com;;]
10008 有道词典:[tcp;;;dict.youdao.com;;]
10010 萤石云:[tcp;;;ys7.com;;,udp;;;;;00:e2|01:62|02:0c,tcp;;11001;;;00:24|01:0a]
10011 掌阅:[tcp;;;ireader.com;;,tcp;;;zhangyue;;]
10012 安居客:[tcp;;;anjuke.com;;]
10013 房天下:[tcp;;;fang.com;;]
10014 58同城:[tcp;;;58.com;;]
10015 动漫之家:[tcp;;;dmzj.com;;]
10016 汽车之家:[tcp;;;autohome.com.cn;;]
10017 飞猪:[tcp;;;fliggy.com;;]
10018 12306:[tcp;;;12306.cn;;]
10019 马蜂窝:[tcp;;;mafengwo.cn;;]
10020 途牛:[tcp;;;tuniu.com;;]
10021 小爱音箱:[tcp;;;ai.xiaomi.com;;,tcp;;;mina.mi.com;;]
10022 搜狗拼音:[tcp;;;pinyin.sogou.com;;]:5:1
#class finance 14 金融
14001 建设银行:[tcp;;;ccb.com;;]
14002 农业银行:[tcp;;;abchina.com;;]
14003 中国银行:[tcp;;;boc.cn;;]
14004 交通银行:[tcp;;;bankcomm.com;;]
14005 招商银行:[tcp;;;cmbchina.com;;]
14006 邮政储蓄:[tcp;;;psbc.com;;]
14007 兴业银行:[tcp;;;cib.com.cn;;]
14008 浦发银行:[tcp;;;spdb.com.cn;;]
14009 中信银行:[tcp;;;citicbank.com;;]
14010 上海银行:[tcp;;;bosc.cn;;]
14011 平安银行:[tcp;;;pingan.com.cn;;]
14012 人民银行:[tcp;;;pbc.gov.cn;;]
14013 北京银行:[tcp;;;bankofbeijing;;]
14014 银联在线:[tcp;;;95516.com;;]
#class tools 11 工具
11001 samba共享:[tcp;;445;;;]
11002 ftp文件传输:[tcp;;21;;;]
11003 SSH:[tcp;;;;;00:53|01:53|02:48]
+234
View File
@@ -0,0 +1,234 @@
#version v22.3.24
#format v2.0
#id name:[proto;sport;dport;host url;request;dict]
#class chat 1 聊天
1003 微博:[tcp;;443;weibo;;]
1004 陌陌:[tcp;;;momo;;,tcp;;;;;04:2f|05:66|06:65|07:65,tcp;;;;;00:03|01:03|02:00]
1005 支付宝:[tcp;;443;alipay.com;;]
1006 钉钉:[tcp;;;dingtalk;;,tcp;;;;d?host=;,tcp;;;;/man/api;,tcp;;;;/beacon;]
1007 Soul:[tcp;;;soulapp;;]
1008 伊对:[tcp;;;520yidui;;]
1009 探探:[tcp;;;tancdn;;,tcp;;;tantanapp;;]
1010 多闪:[tcp;;;ppkankan;;]
#class game 2 游戏
2001 王者荣耀:[tcp;;;;;00:33|1:66|02:00|03:0b]
2002 和平精英:[tcp;;17500;;;00:33|1:66|03:0a|05:0a]
2003 英雄联盟手游:[tcp;;;;;00:33|01:66|02:00|03:0b,tcp;;443;;;00:01|01:00|10:86|11:47]
2015 我的世界:[tcp;;443;g79mclobt.nie.netease;;]
2005 欢乐斗地主:[tcp;;8000;;;00:74|01:67|02:77|03:5f]
2006 梦幻西游:[tcp;;;;;00:0e|01:00|02:fe|03:ff]
2007 明日之后:[udp;;;;;00:05|01:09|02:00,tcp;;;;;00:02|01:00|02:00|03:00|04:00|05:00]
2008 QQ飞车:[udp;;;;;00:28|01:28,tcp;;10000;;;00:33|01:66|02:00|03:08]
2009 跑跑卡丁车:[tcp;;8888;;;00:33|01:66|02:00|03:08]
2010 开心消消乐:[tcp;;80;happyelements;;]
2011 狂野飙车:[tcp;;;asphalt9;;]
2012 率土之滨:[tcp;;10001;;;00:00|01:00,tcp;;8001;;;00:00|01:00]
2013 一刀传世:[tcp;;8040;;;00:47|01:45]
2014 第五人格:[tcp;;4010;;;,tcp;;4010;;;,tcp;;4020;;;,tcp;;4030;;;,tcp;;4040;;;,tcp;;4050;;;,tcp;;4060;;;,tcp;;4070;;;,tcp;;4080;;;,tcp;;4090;;;]
2016 皇室战争:[udp;;9339;;;]
2017 炉石传说:[tcp;;3724;;;00:73:01:00:02:00]
2023 原神:[tcp;;443;yuanshen.com;;]
2025 天涯明月刀:[tcp;;10000;;;00:43|01:66|02:aa]
2026 微信小游戏:[tcp;;443;mmgame;;,tcp;;443;game.weixin.qq;;]
2033 我叫MT4:[tcp;;21248;;;,tcp;;;dir.mt4.qq.com;;]
2034 神都夜行录:[udp;;;;;00:00|01:00|02:00|03:00|04:56|05:40]
2041 光遇:[udp;;10000-15000;;;00:8f|01:ff,tcp;;;ma75.update.netease.com;;,tcp;;;ma75.proxima.nie.netease;;]
2042 保卫萝卜4:[tcp;;;s4.luobo.cn;;]
2040 哈利波特:[tcp;;10021-12000;;;00:02|01:00|02:00|03:00|04:00|05:00,tcp;;443;g92.proxima;;]
2067 9377游戏:[tcp;;;www.9377.com;;]
2068 4399游戏:[tcp;;;4399.com;;]
2069 7k7k游戏:[tcp;;;7k7k.com;;]
2070 17173游戏:[tcp;;;17173.com;;]
2071 37网游:[tcp;;;37.com;;]
2072 游民星空:[tcp;;;gamersky.com;;]
2073 游侠网:[tcp;;;ali213.net;;]
2074 hao123游戏:[tcp;;;game.hao123.com;;]
2075 51游戏:[tcp;;;www.51.com;;]
2050 uu加速器:[tcp;;;mg.uu.163.com;;]
2051 腾讯加速器:[tcp;;;m.acc.qq.com;;]
2080 乐逗游戏:[tcp;;;.uu.cc;;]
#class video 3 视频
3001 抖音短视频:[tcp;;;-dy-;;,tcp;;;-dy.;;,tcp;;;douyin;;]
3002 火山小视频:[tcp;;;.huoshan.com;;,tcp;;;hs.pstatp.com;;,tcp;;;hs.ixigua.com;;]
3003 腾讯视频:[tcp;;443;v.qq.com;;,tcp;;443;video.qq.com;;,tcp;;443;btrace.qq.com;;]
3004 爱奇艺:[tcp;;;iqiyi;;,tcp;;;qy.net;;]
3005 微视:[tcp;;80;;;00:34|01:16|02:75,tcp;;80;weishi.qq.com;;]
3006 斗鱼直播:[tcp;;;douyu;;,tcp;;;douyu;;-2:2f|-1:00]
3008 虎牙直播:[tcp;;;huya;;,udp;;;;;01:00|02:00|03:00|04:23,udp;;;;;01:00|02:00|03:00|04:24]
3009 快手:[tcp;;;kuaishou;;,tcp;;;ksyuncdn.com;;,tcp;;;.gifshow.com;;,tcp;;;yximgs.com;;,tcp;;80;;/ksc;,tcp;;;kwaicdn;;,tcp;;;kwimgs;;]
3010 小红书:[tcp;;;xiaohongshu;;,tcp;;;xhscdn;;]
3011 花椒直播:[tcp;;;huajiao;;]
3012 映客直播:[tcp;;;;.inke.cn;]
3013 YY:[udp;;;;;02:00|03:00|04:08,udp;;;;;00:4f|01:00|02:00]
3014 哔哩哔哩:[tcp;;;bilivideo;;,tcp;;;bilibili.com;;,tcp;;;;;00:47|05:75|06:70|07:67,tcp;;;;/bfs/emote/;,,tcp;;;hdslb.com;;]
3016 芒果tv:[tcp;;443;mgtv;;,tcp;;80;mgtv;;,tcp;;443;hitv;;]
3017 西瓜视频:[tcp;;;ixigua;;,tcp;;443;snsdk;;,tcp;;;xg-p.ixigua;;,tcp;;;bdxigua;;]
3018 搜狐视频:[tcp;;;aty.sohu.com;;,tcp;;;tv.itc.cn;;]
3019 播聊:[tcp;;80;randlove.cn;;,tcp;;;yueliao;;,tcp;;;5glive;;]
3020 咪咕视频:[tcp;;;miguvideo;;,tcp;;;migu.cn;;]
3021 韩剧TV:[tcp;;;hanju.koudaibaobao;;]
3022 人人视频:[tcp;;;rr.tv;;]
3023 央视影音:[tcp;;;cntv;;]
3024 土豆视频:[tcp;;;youku;;,tcp;;;ykimg;;]
3025 最右:[tcp;;;izuiyou;;]
3026 风行视频:[tcp;;;funshion;;]
3027 企鹅电竞:[tcp;;;egame.qq;;,tcp;;;liveplay;;,tcp;;;;pggame;]
3028 波波视频:[tcp;;;miaopai;;]
3029 酷狗短酷:[tcp;;;bssdl.kugou;;]
3030 酷狗直播:[tcp;;;rt-m.kugou;;,tcp;;;kgimg.com;;]
#class shopping 4 购物
4001 淘宝:[tcp;;;taobao;;,tcp;;;alicdn.com;;,tcp;;;tmall.com;;,tcp;;;;;00:d3|01:00,,tcp;;;;;00:d4|01:00,,tcp;;;;;00:d3|01:00]
4002 京东:[tcp;;;360buyimg;;,tcp;;;jd.com;;,tcp;;;jdcdn.com;;,tcp;;;;;00:d5|01:00]
4003 唯品会:[tcp;;;vips-mobile;;,tcp;;;vipshop;;,tcp;;;vip.com;;,tcp;;;vipstatic.com;;,tcp;;;appsimg.com;;]
4004 拼多多:[tcp;;;pinduoduo;;,tcp;;;yangkeduo.com;;,tcp;;;s1p.cdntip.com;;]
4010 饿了么:[tcp;;;eleme;;]
4011 美团:[tcp;;;meituan;;]
4012 闲鱼:[tcp;;;xianyu;;]
4021 转转:[tcp;;;zhuanzhuan;;,tcp;;;zhuanstatic;;]
4005 蘑菇街:[tcp;;;mogujie;;,tcp;;;mogucdn;;,tcp;;;;;00:73|01:ea|02:68|03:fb|04:3f]
4006 苏宁易购:[tcp;;;.suning.;;]
4007 当当网:[tcp;;;.dangdang.com;;]
4008 1号店:[tcp;;;.yhd.com;;]
4009 朴朴超市:[tcp;;;pupumall;;,tcp;;;pupuapi;;]
4013 叮咚买菜:[tcp;;;ddxq.mobi;;]
4014 小米有品:[tcp;;;youpin;;,tcp;;;shopapi.io.mi.com;;]
4015 微店:[tcp;;;weidian;;]
4016 折800:[tcp;;;zhe800.com;;]
4017 HM:[tcp;;;www.hm.com;;,tcp;;;measurement.com;;]
4018 好省:[tcp;;;hzhstb.com;;]
4019 什么值得买:[tcp;;;smzdm.com;;]
4020 大众点评:[tcp;;;dianping.com;;]
4022 网易严选:[tcp;;;yanxuan;;]
4023 识货:[tcp;;;shihuo;;]
4024 考拉海购:[tcp;;;kaola;;]
4025 宜家家居:[tcp;;;ikea.cn;;]
4026 小象优品:[tcp;;;xiaoxiangyoupin;;]
#class music 5 音乐
5001 网易云音乐:[tcp;;;music.163;;,tcp;;;music.126;;]
5002 QQ音乐:[tcp;;;;^/amobile.music.tc.qq.com;,tcp;;;qqmusic;;]
5003 酷狗音乐:[tcp;;;kugou;;,tcp;;;kgimg;;,tcp;;;fanxing;;]
5004 酷我音乐:[tcp;;;.kuwo.cn;;]
5005 喜马拉雅:[tcp;;;.ximalaya.com;;]
5006 千千音乐:[tcp;;;music.taihe.com;;]
5007 虾米音乐:[tcp;;;xiami;;]
5008 音悦台:[tcp;;;yinyuetai.com;;]
5009 豆瓣FM:[tcp;;;douban.fm;;]
5010 唱吧:[tcp;;;changba.com;;]
5011 音乐随心听:[tcp;;;fm.taihe.com;;]
5012 懒人听书:[tcp;;;lrts.me;;]
#class employee 6 招聘
6001 前程无忧:[tcp;;;51job;;]
6002 智联招聘:[tcp;;;zhaopin;;]
6003 猎聘:[tcp;;;liepin;;]
6004 赶集网:[tcp;;;58.com;;,tcp;;;58cdn;;]
6005 同城急聘:[tcp;;;xiaomei;;]
6006 领英:[tcp;;;linkedin;;]
6007 斗米:[tcp;;;doumi;;]
6008 看准:[tcp;;;kanzhun.com;;]
6009 应届生求职:[tcp;;;yingjiesheng.com;;]
6010 中华英才网:[tcp;;;chinahr.com;;]
6011 拉勾网:[tcp;;;lagou.com;;]
6012 大街网:[tcp;;;dajie.com;;]
6013 boss直聘:[tcp;;;zhipin.com;;]
6014 实习僧:[tcp;;;shixiseng.com;;]
#class download 7 下载
7001 迅雷:[udp;12345;;;;,udp;15000;;;;,tcp;;54321;;;,tcp;;12345;;;,udp;6881;;;;,udp;;12346;;;,udp;12346;;;;]
7002 AppStore:[tcp;;;itunes.apple.com;;] HIDE:0
7003 samba共享:[tcp;;445;;;] HIDE:0
7004 ftp文件传输:[tcp;;21;;;] HIDE:0
7005 vivo应用商店:[tcp;;443;appstore.vivo;;,tcp;;443;apkappdefwsdl.vivo;;] HIDE:0
7006 王者荣耀更新:[tcp;;80;;/sgame/;]
7007 天翼云盘:[tcp;;;ctyunapi;;]
7008 腾讯微云:[tcp;;;weiyun.com;;,tcp;;;aegis.qq.com;;,tcp;;;pingtas.qq.com;;,tcp;;443;;;00:77|01:6e|02:73]
7009 坚果云:[tcp;;;jianguoyun;;]
7010 蓝奏云:[tcp;;;pan.lanzou.com;;]
7011 华为云:[tcp;;;cloud.huawei.com;;,tcp;;;hicloud.com;;,tcp;;;myhuaweicloud.cn;;]
7020 windows更新:[tcp;;80;update.microsoft.com;;,tcp;;;windowsupdate.com;;]
7030 向日葵:[tcp;;;oray.com;;,tcp;;;oray.net;;]
7031 TeamViewer:[tcp;;;teamviewer;;]
7032 阿里云盘:[tcp;;;aliyundrive;;]
7035 SSH:[tcp;;;;;00:53|01:53|02:48]
#class website 8 常用网站
8001 百度:[tcp;;;baidu.com;;]
8002 新浪:[tcp;;;sina.com;;]
8003 搜狐:[tcp;;;sohu.com;;]
8004 网易:[tcp;;;163.com;;,tcp;;443;126.com;;]
8005 凤凰网:[tcp;;;ifeng.com;;]
8006 人民网:[tcp;;;people.com.cn;;]
8007 凤凰网:[tcp;;;ifeng.com;;]
8008 中华网:[tcp;;;china.com;;]
8009 hao123:[tcp;;;hao123.com;;,]
8010 2345:[tcp;;;2345.com;;,]
8011 4399游戏:[tcp;;;4399.com;;]
8012 7k7k游戏:[tcp;;;7k7k.com;;]
8013 17173游戏:[tcp;;;17173.com;;]
8014 37网游:[tcp;;;37.com;;]
8015 游民星空:[tcp;;;gamersky.com;;]
8016 游侠网:[tcp;;;ali213.net;;]
8017 世纪佳缘:[tcp;;;jiayuan.com;;]
8018 珍爱网:[tcp;;;zhenai.com;;]
8019 百合网:[tcp;;;baihe.com;;]
8020 天涯社区:[tcp;;;tianya.cn;;]
8021 携程网:[tcp;;;ctrip.com;;]
8022 飞猪:[tcp;;;fliggy.com;;]
8023 12306:[tcp;;;12306.cn;;]
8024 马蜂窝:[tcp;;;mafengwo.cn;;]
8025 途牛:[tcp;;;tuniu.com;;]
8026 穷游网:[tcp;;;qyer.com;;]
8027 驴妈妈:[tcp;;;lvmama.com;;]
8028 同程旅游:[tcp;;;ly.com;;]
8029 太平洋汽车:[tcp;;;pcauto.com.cn;;]
8030 易车网:[tcp;;;bitauto.com;;]
8031 爱卡汽车:[tcp;;;xcar.com.cn;;]
8032 雪球:[tcp;;;xueqiu.com;;]
8033 东方财富:[tcp;;;eastmoney.com;;]
8034 证券之星:[tcp;;;stockstar.com;;]
8035 和讯:[tcp;;;hexun.com;;]
8036 第一财经:[tcp;;;yicai.com;;]
8037 全景网:[tcp;;;p5w.net;;]
8038 中彩网:[tcp;;;zhcw.com;;]
8039 中国体育彩票:[tcp;;;lottery.gov.cn;;]
8040 竞彩网:[tcp;;;sporttery.cn;;]
8041 豆丁:[tcp;;;docin.com;;]
8042 豆瓣:[tcp;;;douban.com;;]
8043 知乎:[tcp;;;zhihu.com;;]
8044 缤客:[tcp;;;booking.com;;]
8046 猫扑:[tcp;;;mop.com;;]
8047 赶集网:[tcp;;;ganji.com;;]
8048 安居客:[tcp;;;anjuke.com;;]
8049 房天下:[tcp;;;fang.com;;]
8050 链家:[tcp;;;lianjia.com;;]
8051 百姓网:[tcp;;;baixing.com;;]
8052 下厨房:[tcp;;;xiachufang.com;;]
8053 大众点评:[tcp;;;dianping.com;;]
8054 58同城:[tcp;;;58.com;;]
8055 天眼查:[tcp;;;tianyancha.com;;]
8056 千图网:[tcp;;;58pic.com;;]
8057 csdn社区:[tcp;;;csdn.net;;]
8058 有道词典:[tcp;;;dict.youdao.com;;]
8059 动漫之家:[tcp;;;dmzj.com;;]
8060 汽车之家:[tcp;;;autohome.com.cn;;]
8061 纵横中文网:[tcp;;;zongheng.com;;]
8062 起点中文网:[tcp;;;qidian.com;;]
8063 飞卢:[tcp;;;faloo.com;;]
8064 潇湘书院:[tcp;;;xxsy.net;;]
8065 cctv5:[tcp;;;sports.cctv.com;;]
8066 虎扑体育:[tcp;;;www.hupu.com;;]
8067 建设银行:[tcp;;;ccb.com;;]
8068 农业银行:[tcp;;;abchina.com;;]
8069 中国银行:[tcp;;;boc.cn;;]
8070 交通银行:[tcp;;;bankcomm.com;;]
8071 招商银行:[tcp;;;cmbchina.com;;]
8072 邮政储蓄:[tcp;;;psbc.com;;]
8073 兴业银行:[tcp;;;cib.com.cn;;]
8074 浦发银行:[tcp;;;spdb.com.cn;;]
8075 中信银行:[tcp;;;citicbank.com;;]
8076 上海银行:[tcp;;;bosc.cn;;]
+99
View File
@@ -0,0 +1,99 @@
#version v22.11.11
#format v2.0
#id name:[proto;sport;dport;host url;request;dict]
#class chat 1 Chat
1001 Facebook:[tcp;;;facebook.com;;]
1002 Whatsapp:[tcp;;;whatsapp;;]
1003 Twitter:[tcp;;;twitter.com;;]
1004 Instagram:[tcp;;;instagram.com;;]
1005 VK:[tcp;;;vk.com;;]
1006 Line:[tcp;;;line;;]
1007 Snapchat:[tcp;;;snapchat.com;;]
1008 Tinder:[tcp;;;tinder.com;;]
#class video 3 Video
3001 YouTube:[tcp;;;youtube;;]
3002 Tiktok:[tcp;;;tiktok;;]
3003 NetFlix:[tcp;;;netflix;;]
3004 Vimeo:[tcp;;;vimeo;;]
3005 DailyMotion:[tcp;;;dailymotion;;]
3006 Hulu:[tcp;;;hulu;;]
3007 Vube:[tcp;;;vube;;]
3008 Twitch:[tcp;;;twitch;;]
3009 LiveLeak:[tcp;;;itemfix;;]
3010 Spotify:[tcp;;;spotify.com;;]
3050 Xvideos:[tcp;;;xvideos.com;;]
3051 Pornhub:[tcp;;;pornhub.com;;]
3052 Xnxx:[tcp;;;xnxx.com;;]
#class shopping 4 Shopping
4001 Amazon:[tcp;;;amazon.com;;]
4002 eBay:[tcp;;;ebay.com;;]
4003 Etsy:[tcp;;;etsy.com;;]
4004 Wish:[tcp;;;wish.com;;]
4005 Alibaba:[tcp;;;alibaba;;]
4006 Aliexpress:[tcp;;;aliexpress.com;;]
4007 Walmart:[tcp;;;walmart.com;;]
4008 Sears:[tcp;;;sears.com;;]
4009 Kohls:[tcp;;;kohls.com;;]
4010 Costco:[tcp;;;costco.com;;]
4011 Asos:[tcp;;;asos.com;;]
4012 Cuyana:[tcp;;;cuyana.com;;]
#class download 7 Download
7001 GooglePlay:[tcp;;;play.google.com;;]
7002 AppStore:[tcp;;;iosapps.itunes.apple.com;;]
7003 WindowsUpdate:[tcp;;80;update.microsoft.com;;,tcp;;;windowsupdate.com;;]
7050 Speedtest:[tcp;;;speedtest.net;;]
7060 samba:[tcp;;445;;;]
7061 ftp:[tcp;;21;;;]
7062 ssh:[tcp;;22;;;]
#class website 8 Website
8001 Google:[tcp;;;www.google.com;;]
8002 Wiki:[tcp;;;wikipedia.com;;]
8003 Yahoo:[tcp;;;yahoo;;]
8004 Apple:[tcp;;;www.apple.com;;]
8010 Reddit:[tcp;;;reddit.com;;]
8011 Outlook:[tcp;;;outlook.live.com;;]
8012 Naver:[tcp;;;naver.com;;]
8013 Fandom:[tcp;;;fandom.com;;]
8015 Globo:[tcp;;;globo.com;;]
8016 Yelp:[tcp;;;yelp.com;;]
8017 Pinterest:[tcp;;;www.pinterest.com;;]
8018 BBC:[tcp;;;www.bbc.com;;]
8020 Linkedin:[tcp;;;linkedin.com;;]
8022 Merriam-webster:[tcp;;;merriam-webster.com;;]
8027 Dictionary:[tcp;;;dictionary.com;;]
8028 Tripadvisor:[tcp;;;tripadvisor.com;;]
8029 Britannica:[tcp;;;britannica.com;;]
8030 Cambridge:[tcp;;;cambridge.org;;]
8032 Weather:[tcp;;;weather.com;;]
8033 Wiktionary:[tcp;;;wiktionary.org;;]
8034 Espn:[tcp;;;espn.com;;]
8035 Microsoft:[tcp;;;microsoft.com;;]
8038 Gsmarena:[tcp;;;gsmarena.com;;]
8039 Webmd:[tcp;;;webmd.com;;]
8040 Craigslist:[tcp;;;craigslist.org;;]
8041 Cricbuzz:[tcp;;;cricbuzz.com;;]
8042 Mayoclinic:[tcp;;;mayoclinic.org;;]
8043 Timeanddate:[tcp;;;timeanddate.com;;]
8044 Espncricinfo:[tcp;;;espncricinfo.com;;]
8045 Healthline:[tcp;;;healthline.com;;]
8047 Rottentomatoes:[tcp;;;rottentomatoes.com;;]
8049 Thefreedictionary:[tcp;;;thefreedictionary.com;;]
8052 Bestbuy:[tcp;;;bestbuy.com;;]
8053 Indeed:[tcp;;;indeed.com;;]
8058 Samsung:[tcp;;;samsung.com;;]
8059 Investopedia:[tcp;;;investopedia.com;;]
8060 Flashscore:[tcp;;;flashscore.com;;]
8061 Steampowered:[tcp;;;steampowered.com;;]
8064 Roblox:[tcp;;;roblox.com;;]
8065 Nordstrom:[tcp;;;nordstrom.com;;]
8066 Thepiratebay:[tcp;;;thepiratebay.org;;]
8067 Indiatimes:[tcp;;;indiatimes.com;;]
8068 Cnbc:[tcp;;;cnbc.com;;]
8069 Ssyoutube:[tcp;;;ssyoutube.com;;]
8070 Adobe:[tcp;;;adobe.com;;]
8071 Speedtest:[tcp;;;speedtest.net;;]
8072 Lowes:[tcp;;;lowes.com;;]
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
CLASS_NAME_FILE="/tmp/app_class.txt"
f_file=$1
test -z "$f_file" && return
test -f $CLASS_NAME_FILE &&{
rm $CLASS_NAME_FILE
}
cat $f_file |grep "#class" | awk '{print $3 " " $2 " " $4}' >$CLASS_NAME_FILE
+44
View File
@@ -0,0 +1,44 @@
. /usr/share/libubox/jshn.sh
. /lib/functions.sh
IS_BOOT=0
if [ "$1" = "1" ] ; then
IS_BOOT=1
fi
DISABLE_HNAT=$(uci -q get appfilter.global.disable_hnat)
if [ "$DISABLE_HNAT" != "1" ]; then
exit 0
fi
echo "DISABLE_HNAT: $DISABLE_HNAT"
# mt798x
test -d /sys/kernel/debug/hnat && {
echo 0 >/sys/kernel/debug/hnat/hook_toggle
}
# qca ecm
test -d /sys/kernel/debug/ecm/ && {
echo "1000000" > /sys/kernel/debug/ecm/ecm_classifier_default/accel_delay_pkts
}
if [ $IS_BOOT -ne 1 ] ; then
# turbo acc
test -f /etc/config/turboacc && {
uci -q set "turboacc.config.fastpath_fo_hw"="0"
uci -q set "turboacc.config.fastpath_fc_ipv6"="0"
uci -q set "turboacc.config.fastpath"="none"
uci -q set "turboacc.config.fullcone"="0"
uci commit turboacc
/etc/init.d/turboacc restart
}
uci -q set "firewall.@defaults[0].flow_offloading_hw"='0'
uci -q set "firewall.@defaults[0].flow_offloading"='0'
uci -q set "firewall.@defaults[0].fullcone"='0'
uci commit firewall
/etc/init.d/firewall reload
fi
+117
View File
@@ -0,0 +1,117 @@
. /usr/share/libubox/jshn.sh
. /lib/functions.sh
config_apply()
{
test -z "$1" && return 1
if [ -e "/dev/appfilter" ];then
echo "$1" >/dev/appfilter
fi
}
clean_rule()
{
json_init
json_add_int "op" 3
json_add_object "data"
json_str=`json_dump`
config_apply "$json_str"
json_cleanup
}
load_rule()
{
json_init
json_add_int "op" 1
json_add_object "data"
json_add_array "apps"
config_get appid_list rule app_list
if ! test -z "$appid_list";then
for appid in $appid_list:
do
json_add_int "" $appid
done
fi
json_str=`json_dump`
config_apply "$json_str"
json_cleanup
}
load_whitelist_mac()
{
json_init
config_load appfilter
json_add_int "op" 5
json_add_object "data"
json_add_array "mac_list"
config_foreach add_mac_to_array_callback whitelist
json_str=`json_dump`
config_apply "$json_str"
json_cleanup
}
add_mac_to_array_callback() {
local section="$1"
local mac
config_get mac "$section" "mac"
if [ -n "$mac" ]; then
json_add_string "" "$mac"
fi
}
load_mac_list()
{
json_init
config_load appfilter
json_add_int "op" 4
json_add_object "data"
json_add_array "mac_list"
local user_mode=`uci get appfilter.global.user_mode`
if [ x"1" == x"$user_mode" ];then
config_foreach add_mac_to_array_callback af_user
fi
json_str=`json_dump`
config_apply "$json_str"
json_cleanup
}
reload_rule(){
config_load appfilter
clean_rule
load_rule
load_mac_list
load_whitelist_mac
}
reload_base_config(){
! test -d /proc/sys/oaf && return
config_load appfilter
config_get work_mode "global" "work_mode"
config_get lan_ifname "global" "lan_ifname"
config_get user_mode "global" "user_mode"
config_get app_filter_mode "global" "app_filter_mode"
echo "$work_mode" >/proc/sys/oaf/work_mode
echo "$user_mode" >/proc/sys/oaf/user_mode
echo "${app_filter_mode:-0}" >/proc/sys/oaf/app_filter_mode
if [ x"" != x"$lan_ifname" ];then
echo "$lan_ifname" >/proc/sys/oaf/lan_ifname
fi
}
case $1 in
"reload")
reload_base_config
reload_rule
;;
esac
+6
View File
@@ -0,0 +1,6 @@
OBJS:=appfilter_user.o appfilter_netlink.o appfilter_ubus.o appfilter_config.o utils.o main.o
EXEC:=oafd
all: $(OBJS)
$(CC) -o $(EXEC) $(OBJS) $(LIBS)
clean:
rm $(EXEC) *.o
+124
View File
@@ -0,0 +1,124 @@
#ifndef __APPFILTER_H__
#define __APPFILTER_H__
#define MIN_INET_ADDR_LEN 7
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
#include "utils.h"
#define LOG_FILE_PATH "/tmp/log/appfilter.log"
#define OAF_VERSION "6.1.8"
typedef enum {
LOG_LEVEL_ERROR,
LOG_LEVEL_WARN,
LOG_LEVEL_INFO,
LOG_LEVEL_DEBUG
} LogLevel;
extern int current_log_level;
static void af_log(LogLevel level, const char *format, ...){
if (level > current_log_level)
return;
FILE *log_file = fopen(LOG_FILE_PATH, "a");
if (!log_file) {
perror("Failed to open log file");
return;
}
time_t now = time(NULL);
struct tm *t = localtime(&now);
char time_str[20];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", t);
const char *level_str;
switch (level) {
case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break;
case LOG_LEVEL_INFO: level_str = "INFO"; break;
case LOG_LEVEL_WARN: level_str = "WARN"; break;
case LOG_LEVEL_ERROR: level_str = "ERROR"; break;
default: level_str = "UNKNOWN"; break;
}
fprintf(log_file, "[%s] [%s] ", time_str, level_str);
va_list args;
va_start(args, format);
vfprintf(log_file, format, args);
va_end(args);
fclose(log_file);
}
#define LOG_DEBUG(format, ...) af_log(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
#define LOG_INFO(format, ...) af_log(LOG_LEVEL_INFO, format, ##__VA_ARGS__)
#define LOG_WARN(format, ...) af_log(LOG_LEVEL_WARN, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) af_log(LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
#define MAX_TIME_LIST_LEN 1024
#define MAX_TIME_LIST 64
typedef struct af_time
{
int hour;
int min;
} af_time_t;
typedef struct af_global_config_t{
int enable;
int user_mode;
int work_mode;
int record_enable;
int disable_hnat;
int auto_load_engine;
int tcp_rst;
int disable_quic;
int app_filter_mode; // 0 = specified apps, 1 = all apps
char lan_ifname[16];
}af_global_config_t;
typedef struct time_config{
af_time_t start_time;
af_time_t end_time;
int days[7];
}time_config_t;
typedef struct daily_limit_config {
int enable;
int am_time;
int pm_time;
} daily_limit_config_t;
typedef struct af_time_config_t{
int time_mode;
time_config_t seg_time;
int deny_time;
int allow_time;
int days[7];
int time_num;
time_config_t time_list[MAX_TIME_LIST];
daily_limit_config_t daily_limit[7];
}af_time_config_t;
typedef struct af_config_t{
af_global_config_t global;
af_time_config_t time;
}af_config_t;
typedef struct af_run_time_status{
int deny_time;
int allow_time;
int filter;
int match_time;
int remain_time;
int used_time;
int period_blocked;
}af_run_time_status_t;
extern af_config_t g_af_config;
#endif
+552
View File
@@ -0,0 +1,552 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "appfilter_config.h"
#include "appfilter.h"
#include <uci.h>
app_name_info_t app_name_table[MAX_SUPPORT_APP_NUM];
int g_app_count = 0;
int g_cur_class_num = 0;
char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN];
const char *config_path = "./config";
static struct uci_context *uci_ctx = NULL;
static struct uci_package *uci_appfilter;
int af_uci_get_int_value(struct uci_context *ctx, char *key)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = -1;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
goto done;
}
e = ptr.last;
switch(e->type) {
case UCI_TYPE_SECTION:
ret = -1;
goto done;
case UCI_TYPE_OPTION:
ret = atoi(ptr.o->v.string);
goto done;
default:
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_get_value(struct uci_context *ctx, char *key, char *output, int out_len)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
ret = 1;
goto done;
}
e = ptr.last;
switch(e->type) {
case UCI_TYPE_SECTION:
snprintf(output, out_len, "%s", ptr.s->type);
break;
case UCI_TYPE_OPTION:
snprintf(output, out_len, "%s", ptr.o->v.string);
break;
default:
ret = 1;
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_delete(struct uci_context *ctx, char *key)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
ret = uci_delete(ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(ctx, ptr.p);
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_add_list(struct uci_context *ctx, char *key, char *value)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters;
if (strlen(value) + strlen(key) >= MAX_PARAM_LIST_LEN - 1) {
printf("value too long\n");
return -1;
}
char param_tmp[MAX_PARAM_LIST_LEN] = {0};
sprintf(param_tmp, "%s=%s", key, value);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
ret = uci_add_list(ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(ctx, ptr.p);
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_get_list_value(struct uci_context *ctx, char *key, char *output, int out_len, char *delimt)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = -1;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
goto done;
}
int sep = 0;
e = ptr.last;
int len = 0;
switch(e->type) {
case UCI_TYPE_SECTION:
ret = -1;
goto done;
case UCI_TYPE_OPTION:
if (UCI_TYPE_LIST == ptr.o->type){
memset(output, 0x0, out_len);
uci_foreach_element(&ptr.o->v.list, e) {
len = strlen(output);
if (sep){
strncat(output + len, delimt, out_len);
}
len = strlen(output);
sprintf(output + len, "%s", e->name);
sep = 1;
}
ret = 0;
}
goto done;
default:
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_add_int_list(struct uci_context *ctx, char *key, int value)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
sprintf(param_tmp, "%s=%d", key, value);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
ret = uci_add_list(ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(ctx, ptr.p);
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_del_list(struct uci_context *ctx, char *key, char *value)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
sprintf(param_tmp, "%s=%s", key, value);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
ret = uci_del_list(ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(ctx, ptr.p);
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_set_value(struct uci_context *ctx, char *key, char *value)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[2048] = {0};
sprintf(param_tmp, "%s=%s", key, value);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
e = ptr.last;
ret = uci_set(ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(ctx, ptr.p);
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_set_int_value(struct uci_context *ctx, char *key, int value)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
sprintf(param_tmp, "%s=%d", key, value);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
e = ptr.last;
ret = uci_set(ctx, &ptr);
if (ret == UCI_OK)
ret = uci_save(ctx, ptr.p);
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int af_uci_del_array_value(struct uci_context *ctx, char *key_fmt, int index){
char key[128] = {0};
sprintf(key, key_fmt, index);
return af_uci_delete(ctx, key);
}
int af_uci_set_array_value(struct uci_context *ctx, char *key_fmt, int index, char *value){
char key[128] = {0};
sprintf(key, key_fmt, index);
return af_uci_set_value(ctx, key, value);
}
int af_uci_commit(struct uci_context *ctx, const char * package) {
struct uci_ptr ptr;
int ret = UCI_OK;
if (!package){
return -1;
}
if (uci_lookup_ptr(ctx, &ptr, package, true) != UCI_OK) {
return -1;
}
if (uci_commit(ctx, &ptr.p, false) != UCI_OK) {
ret = -1;
goto done;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return UCI_OK;
}
int af_get_uci_list_num(struct uci_context * ctx, char *package, char *section){
int count = 0;
struct uci_ptr p;
struct uci_element *e;
struct uci_package *pkg = NULL;
if (UCI_OK != uci_load(ctx, package, &pkg)){
return -1;
}
uci_foreach_element(&pkg->sections, e){
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, section)){
continue;
}
count++;
}
uci_unload(ctx, pkg);
return count;
}
int af_uci_get_array_value(struct uci_context *ctx, char *key_fmt, int index, char *output, int out_len)
{
char key[128] = {0};
sprintf(key, key_fmt, index);
return af_uci_get_value(ctx, key, output, out_len);
}
int af_uci_add_section(struct uci_context * ctx, char *package_name, char *section)
{
struct uci_section *s = NULL;
struct uci_package *p = NULL;
int ret;
ret = uci_load(ctx, package_name , &p);
if (ret != UCI_OK)
goto done;
ret = uci_add_section(ctx, p, section, &s);
if (ret != UCI_OK)
goto done;
ret = uci_save(ctx, p);
done:
if (s)
fprintf(stdout, "%s\n", s->e.name);
return ret;
}
//
static struct uci_package *
config_init_package(const char *config)
{
struct uci_context *ctx = uci_ctx;
struct uci_package *p = NULL;
if (!ctx)
{
ctx = uci_alloc_context();
uci_ctx = ctx;
ctx->flags &= ~UCI_FLAG_STRICT;
//if (config_path)
// uci_set_confdir(ctx, config_path);
}
else
{
p = uci_lookup_package(ctx, config);
if (p)
uci_unload(ctx, p);
}
if (uci_load(ctx, config, &p))
return NULL;
return p;
}
char *get_app_name_by_id(int id)
{
int i;
for (i = 0; i < g_app_count; i++)
{
if (id == app_name_table[i].id)
return app_name_table[i].name;
}
return "";
}
void init_app_name_table(void)
{
int count = 0;
char line_buf[2048] = {0};
FILE *fp = fopen("/tmp/feature.cfg", "r");
if (!fp)
{
printf("open file failed\n");
return;
}
g_app_count = 0;
while (fgets(line_buf, sizeof(line_buf), fp))
{
if (strstr(line_buf, "#"))
continue;
if (strlen(line_buf) < 10)
continue;
if (!strstr(line_buf, ":"))
continue;
char *pos1 = strstr(line_buf, ":");
char app_info_buf[128] = {0};
int app_id;
char app_name[64] = {0};
memset(app_name, 0x0, sizeof(app_name));
strncpy(app_info_buf, line_buf, pos1 - line_buf);
sscanf(app_info_buf, "%d %s", &app_id, app_name);
app_name_table[g_app_count].id = app_id;
strcpy(app_name_table[g_app_count].name, app_name);
g_app_count++;
}
fclose(fp);
}
void init_app_class_name_table(void)
{
char line_buf[2048] = {0};
int class_id;
char class_name[64] = {0};
FILE *fp = fopen("/tmp/app_class.txt", "r");
if (!fp)
{
printf("open file failed\n");
return;
}
g_cur_class_num = 0;
while (fgets(line_buf, sizeof(line_buf), fp))
{
sscanf(line_buf, "%d %*s %s", &class_id, class_name);
strcpy(CLASS_NAME_TABLE[class_id - 1], class_name);
g_cur_class_num++;
}
fclose(fp);
}
//00:00 9:1
int check_time_valid(char *t)
{
if (!t)
return 0;
if (strlen(t) < 3 || strlen(t) > 5 || (!strstr(t, ":")))
return 0;
else
return 1;
}
int config_get_appfilter_enable(void)
{
int enable = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return -1;
enable = af_uci_get_int_value(ctx, "appfilter.global.enable");
if (enable < 0)
enable = 0;
uci_free_context(ctx);
return enable;
}
int config_get_lan_ip(char *lan_ip, int len)
{
int ret = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return -1;
ret = af_uci_get_value(ctx, "network.lan.ipaddr", lan_ip, len);
uci_free_context(ctx);
return ret;
}
int config_get_lan_mask(char *lan_mask, int len)
{
int ret = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return -1;
ret = af_uci_get_value(ctx, "network.lan.netmask", lan_mask, len);
uci_free_context(ctx);
return ret;
}
int appfilter_config_alloc(void)
{
char *err;
uci_appfilter = config_init_package("appfilter");
if (!uci_appfilter)
{
uci_get_errorstr(uci_ctx, &err, NULL);
printf("Failed to load appfilter config (%s)\n", err);
free(err);
return -1;
}
return 0;
}
int appfilter_config_free(void)
{
if (uci_appfilter)
{
uci_unload(uci_ctx, uci_appfilter);
uci_appfilter = NULL;
}
if (uci_ctx)
{
uci_free_context(uci_ctx);
uci_ctx = NULL;
}
}
+68
View File
@@ -0,0 +1,68 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef __APPFILTER_CONFIG_H__
#define __APPFILTER_CONFIG_H__
#include <uci.h>
#define MAX_SUPPORT_APP_NUM 1024
#define MAX_CLASS_NAME_LEN 32
#define MAX_PARAM_LIST_LEN 1024
#include "appfilter_user.h"
extern int g_cur_class_num;
extern int g_app_count;
extern char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN];
typedef struct app_name_info
{
int id;
char name[64];
} app_name_info_t;
void init_app_name_table(void);
void init_app_class_name_table(void);
char *get_app_name_by_id(int id);
int appfilter_config_alloc(void);
int appfilter_config_free(void);
int config_get_appfilter_enable(void);
int config_get_lan_ip(char *lan_ip, int len);
int config_get_lan_mask(char *lan_mask, int len);
int af_uci_delete(struct uci_context *ctx, char *key);
int af_uci_add_list(struct uci_context *ctx, char *key, char *value);
int af_uci_add_int_list(struct uci_context *ctx, char *key, int value);
int af_uci_del_list(struct uci_context *ctx, char *key, char *value);
int af_uci_get_list_value(struct uci_context *ctx, char *key, char *output, int out_len, char *delimt);
int af_uci_set_value(struct uci_context *ctx, char *key, char *value);
int af_uci_set_int_value(struct uci_context *ctx, char *key, int value);
int af_uci_del_array_value(struct uci_context *ctx, char *key_fmt, int index);
int af_uci_set_array_value(struct uci_context *ctx, char *key_fmt, int index, char *value);
int af_get_uci_list_num(struct uci_context * ctx, char *package, char *section);
int af_uci_get_array_value(struct uci_context *ctx, char *key_fmt, int index, char *output, int out_len);
int af_uci_get_int_value(struct uci_context *ctx, char *key);
int af_uci_get_value(struct uci_context *ctx, char *key, char *output, int out_len);
int af_uci_add_section(struct uci_context * ctx, char *package_name, char *section);
int af_uci_commit(struct uci_context *ctx, const char * package);
char *get_app_name_by_id(int id);
#endif
+279
View File
@@ -0,0 +1,279 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/socket.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <libubox/uloop.h>
#include <libubox/utils.h>
#include <libubus.h>
#include <json-c/json.h>
#include "appfilter_user.h"
#include "appfilter_netlink.h"
#include "appfilter.h"
#include "appfilter_config.h"
#define MAX_NL_RCV_BUF_SIZE 4096
#define REPORT_INTERVAL_SECS 60
extern int hash_appid(int appid);
extern unsigned int g_feature_update_time;
void appfilter_nl_handler(struct uloop_fd *u, unsigned int ev)
{
int ret;
int i;
char buf[MAX_NL_RCV_BUF_SIZE];
struct sockaddr_nl nladdr;
struct iovec iov = {buf, sizeof(buf)};
struct nlmsghdr *h;
int type;
int id;
char *mac = NULL;
u_int32_t cur_time = get_timestamp();
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
do
{
ret = recvmsg(u->fd, &msg, 0);
} while ((-1 == ret) && (EINTR == errno));
if (ret < 0)
{
printf("recv msg error\n");
return;
}
else if (0 == ret)
{
return;
}
h = (struct nlmsghdr *)buf;
char *kmsg = (char *)NLMSG_DATA(h);
struct af_msg_hdr *af_hdr = (struct af_msg_hdr *)kmsg;
if (af_hdr->magic != 0xa0b0c0d0)
{
printf("magic error %x\n", af_hdr->magic);
return;
}
if (af_hdr->len <= 0 || af_hdr->len >= MAX_OAF_NETLINK_MSG_LEN)
{
printf("data len error\n");
return;
}
char *kdata = kmsg + sizeof(struct af_msg_hdr);
struct json_object *root = json_tokener_parse(kdata);
if (!root)
{
printf("parse json failed:%s", kdata);
return;
}
LOG_DEBUG("report %s\n", kdata);
struct json_object *mac_obj = json_object_object_get(root, "mac");
if (!mac_obj)
{
printf("parse mac obj failed\n");
json_object_put(root);
return;
}
mac = json_object_get_string(mac_obj);
dev_node_t *node = find_dev_node(mac);
if (!node)
{
node = add_dev_node(mac);
if (!node)
{
goto EXIT;
}
}
struct json_object *ip_obj = json_object_object_get(root, "ip");
if (ip_obj)
strncpy(node->ip, json_object_get_string(ip_obj), sizeof(node->ip));
struct json_object *active_obj = json_object_object_get(root, "active");
if (active_obj) {
node->active = json_object_get_int(active_obj);
if (node->active)
{
// 根据当前时间判断是上午还是下午,分别累加
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
int current_hour = tm_info->tm_hour;
if (current_hour < 12) {
// 上午:0:00-11:59
node->today_am_active_time += 1; //min
} else {
// 下午:12:00-23:59
node->today_pm_active_time += 1; //min
}
}
}
struct json_object *up_flow_obj = json_object_object_get(root, "up_flow");
struct json_object *down_flow_obj = json_object_object_get(root, "down_flow");
unsigned long long total_up_bytes = 0;
unsigned long long total_down_bytes = 0;
if (up_flow_obj) {
node->today_up_bytes += (unsigned long long)json_object_get_int64(up_flow_obj) * 1024;
}
if (down_flow_obj) {
node->today_down_bytes += (unsigned long long)json_object_get_int64(down_flow_obj) * 1024;
}
struct json_object *visit_array = json_object_object_get(root, "visit_info");
if (!visit_array)
{
goto EXIT;
}
for (i = 0; i < json_object_array_length(visit_array); i++)
{
struct json_object *visit_obj = json_object_array_get_idx(visit_array, i);
struct json_object *appid_obj = json_object_object_get(visit_obj, "appid");
struct json_object *action_obj = json_object_object_get(visit_obj, "latest_action");
// old appid may be not in the feature list
if (cur_time - g_feature_update_time < 300){
if (strlen(get_app_name_by_id(json_object_get_int(appid_obj))) == 0){
LOG_INFO("ignore appid %d because it is not in the feature list\n", json_object_get_int(appid_obj));
continue;
}
}
int appid = json_object_get_int(appid_obj);
int action = json_object_get_int(action_obj);
type = appid / 1000;
id = appid % 1000;
if (id <= 0 || type <= 0)
continue;
node->stat[type - 1][id - 1].total_time += REPORT_INTERVAL_SECS;
int hash = hash_appid(appid);
visit_info_t *head = node->visit_htable[hash];
visit_info_t *p = head;
while(p){
if((p->appid == appid) && (cur_time - p->latest_time < 300)){
LOG_DEBUG("match appid = %d\n", appid, cur_time - p->latest_time);
break;
}
p = p->next;
}
if (!p){
p = (visit_info_t *)calloc(1, sizeof(visit_info_t));
p->appid = appid;
p->next = NULL;
p->first_time = cur_time;
add_visit_info_node(&node->visit_htable[hash], p);
}
p->action = action;
p->latest_time = cur_time;
}
EXIT:
json_object_put(root);
}
#define MAX_NL_MSG_LEN 1024
int send_msg_to_kernel(int fd, void *msg, int len)
{
struct sockaddr_nl saddr, daddr;
memset(&daddr, 0, sizeof(daddr));
daddr.nl_family = AF_NETLINK;
daddr.nl_pid = 0; // to kernel
daddr.nl_groups = 0;
int ret = 0;
struct nlmsghdr *nlh = NULL;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_NL_MSG_LEN));
nlh->nlmsg_len = NLMSG_SPACE(MAX_NL_MSG_LEN);
nlh->nlmsg_flags = 0;
nlh->nlmsg_type = 0;
nlh->nlmsg_seq = 0;
nlh->nlmsg_pid = DEFAULT_USR_NL_PID;
char msg_buf[MAX_NL_MSG_LEN] = {0};
struct af_msg_hdr *hdr = (struct af_msg_hdr *)msg_buf;
hdr->magic = 0xa0b0c0d0;
hdr->len = len;
char *p_data = msg_buf + sizeof(struct af_msg_hdr);
memcpy(p_data, msg, len);
memcpy(NLMSG_DATA(nlh), msg_buf, len + sizeof(struct af_msg_hdr));
ret = sendto(fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&daddr, sizeof(struct sockaddr_nl));
free(nlh);
if (!ret)
{
perror("sendto error\n");
return -1;
}
return 0;
}
int appfilter_nl_init(void)
{
int fd;
struct sockaddr_nl nls;
fd = socket(AF_NETLINK, SOCK_RAW, OAF_NETLINK_ID);
if (fd < 0)
{
LOG_DEBUG("Connect netlink %d failed %s\n", OAF_NETLINK_ID, strerror(errno));
return -1;
}
memset(&nls, 0, sizeof(struct sockaddr_nl));
nls.nl_pid = DEFAULT_USR_NL_PID;
nls.nl_groups = 0;
nls.nl_family = AF_NETLINK;
if (bind(fd, (void *)&nls, sizeof(struct sockaddr_nl)))
{
LOG_DEBUG("Bind failed %s\n", strerror(errno));
return -1;
}
return fd;
}
+57
View File
@@ -0,0 +1,57 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef __APPFILTER_NETLINK_H__
#define __APPFILTER_NETLINK_H__
#define DEFAULT_USR_NL_PID 999
#define OAF_NETLINK_ID 29
#define MAX_OAF_NETLINK_MSG_LEN 1024
#define MAX_AF_MSG_DATA_LEN 800
#define MAX_FEATURE_LINE_LEN 600
struct af_msg_hdr
{
int magic;
int len;
};
enum E_MSG_TYPE
{
AF_MSG_INIT,
AF_MSG_ADD_FEATURE,
AF_MSG_CLEAN_FEATURE,
AF_MSG_MAX
};
typedef struct af_msg
{
int action;
} af_msg_t;
typedef struct af_feature_msg{
af_msg_t hdr;
char feature[MAX_FEATURE_LINE_LEN];
} af_feature_msg_t;
int appfilter_nl_init(void);
void appfilter_nl_handler(struct uloop_fd *u, unsigned int ev);
int send_msg_to_kernel(int fd, void *msg, int len);
#endif
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef __APPFILTER_UBUS_H__
#define __APPFILTER_UBUS_H__
int appfilter_ubus_init(void);
#endif
File diff suppressed because it is too large Load Diff
+136
View File
@@ -0,0 +1,136 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef __FILTER_USER_H__
#define __FILTER_USER_H__
#include <sys/types.h>
#define MAX_IP_LEN 32
#define MAX_MAC_LEN 32
#define MAX_VISIT_HASH_SIZE 64
#define MAX_DEV_NODE_HASH_SIZE 64
#define MAX_HOSTNAME_SIZE 64
#define OAF_VISIT_LIST_FILE "/tmp/visit_list"
#define OAF_DEV_LIST_FILE "/tmp/dev_list"
#define OAF_USER_FILE "/etc/user_list.dat"
#define MIN_VISIT_TIME 5 // default 5s
#define MAX_APP_STAT_NUM 8
#define MAX_VISITLIST_DUMP_NUM 16
#define MAX_APP_TYPE 32
#define MAX_APP_ID_NUM 512
#define MAX_SUPPORT_DEV_NUM 256
#define SECONDS_PER_DAY (24 * 3600)
#define MAX_NICKNAME_SIZE 64
#define MAX_REPORT_URL_LEN 64
typedef struct visit_info
{
int appid;
u_int32_t first_time;
u_int32_t latest_time;
int action;
int expire;
struct visit_info *next;
} visit_info_t;
typedef struct visit_stat
{
u_int32_t total_time;
} visit_stat_t;
typedef struct dev_node
{
char mac[MAX_MAC_LEN];
char ip[MAX_IP_LEN];
char ipv6[64];
char hostname[MAX_HOSTNAME_SIZE];
char nickname[MAX_NICKNAME_SIZE];
int online;
int expire;
u_int32_t offline_time;
u_int32_t online_time;
visit_info_t *visit_htable[MAX_VISIT_HASH_SIZE];
visit_stat_t stat[MAX_APP_TYPE][MAX_APP_ID_NUM]; // todo: list
char visiting_url[MAX_REPORT_URL_LEN];
int visiting_app;
int is_whitelist;
u_int32_t up_rate;
u_int32_t down_rate;
u_int64_t today_up_bytes;
u_int64_t today_down_bytes;
int active;
u_int32_t today_am_active_time;
u_int32_t today_pm_active_time;
int is_selected;
struct dev_node *next;
} dev_node_t;
struct app_visit_info
{
int app_id;
char app_name[32];
int total_time;
};
struct app_visit_stat_info
{
int num;
struct app_visit_info visit_list[MAX_APP_STAT_NUM];
};
typedef void (*iter_func)(void *arg, dev_node_t *dev);
//todo:dev for each
extern dev_node_t *dev_hash_table[MAX_DEV_NODE_HASH_SIZE];
dev_node_t *add_dev_node(char *mac);
void init_dev_node_htable();
void dump_dev_list(void);
void dump_dev_visit_list(void);
dev_node_t *find_dev_node(char *mac);
void dev_foreach(void *arg, iter_func iter);
void add_visit_info_node(visit_info_t **head, visit_info_t *node);
void check_dev_visit_info_expire(void);
void flush_expire_visit_info();
int check_dev_expire(void);
void flush_dev_expire_node(void);
void flush_expire_visit_info(void);
void flush_offline_users(void);
void save_user_time_to_file(void);
void load_user_time_from_file(void);
void update_dev_list(void);
void update_dev_nickname(void);
void update_dev_visiting_info(void);
void update_dev_whitelist_flag(void);
void update_dev_selected_flag(void);
void clean_invalid_app_records(void);
void clear_device_app_statistics(void);
void check_and_reset_today_active_time(dev_node_t *node);
void reset_all_users_today_active_time(void);
void reset_all_users_today_flow(void);
void check_all_users_period_time(void);
void update_dev_online_status(void);
#endif
+883
View File
@@ -0,0 +1,883 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libubox/uloop.h>
#include <libubox/utils.h>
#include <libubus.h>
#include "appfilter_user.h"
#include "appfilter_netlink.h"
#include "appfilter_ubus.h"
#include "appfilter_config.h"
#include <time.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "appfilter.h"
#include <stdio.h>
#include "utils.h"
#define CMD_GET_LAN_IP_FMT "ifconfig %s | grep 'inet addr' | awk '{print $2}' | awk -F: '{print $2}'"
#define CMD_GET_LAN_MASK_FMT "ifconfig %s | grep 'inet addr' | awk '{print $4}' | awk -F: '{print $2}'"
int current_log_level = LOG_LEVEL_INFO;
af_run_time_status_t g_af_status;
int g_oaf_config_change = 1;
af_config_t g_af_config;
int g_hnat_init = 0;
int g_feature_update = 0;
int g_feature_update_time = 0;
void oaf_timeout_handler(struct uloop_timeout *t);
void af_init_time_status(void){
g_af_status.filter = 0;
g_af_status.deny_time = 0;
g_af_status.allow_time = 0;
g_af_status.match_time = 0;
g_af_status.remain_time = 0;
g_af_status.used_time = 0;
g_af_status.period_blocked = 0;
}
void af_init_status(void){
af_init_time_status();
}
struct uloop_timeout dev_tm = {
.cb = oaf_timeout_handler};
static struct uloop_fd appfilter_nl_fd = {
.cb = appfilter_nl_handler,
};
void apply_time_config_to_uci(af_time_config_t *time_config){
struct uci_context *uci_ctx = uci_alloc_context();
if (!uci_ctx) {
printf("Failed to allocate UCI context\n");
return;
}
af_uci_set_int_value(uci_ctx, "appfilter.time.time_mode", time_config->time_mode);
// Build days string from global weekday array (used as fallback)
char days_str[128] = {0};
int first = 1;
int i, j;
for (i = 0; i < 7; i++) {
if (time_config->days[i] == 1) {
if (!first) {
strcat(days_str, " ");
}
char tmp[8];
snprintf(tmp, sizeof(tmp), "%d", i);
strcat(days_str, tmp);
first = 0;
}
}
af_uci_set_value(uci_ctx, "appfilter.time.days", days_str);
if (time_config->time_mode == 0) {
// Manual mode: write time_list
af_uci_delete(uci_ctx, "appfilter.time.time");
int time_list_len = time_config->time_num;
for (i = 0; i < time_list_len; i++) {
char time_str[256] = {0};
// Build weekday string: "1,2,4,5"
char weekday_str[64] = {0};
first = 1;
for (j = 0; j < 7; j++) {
if (time_config->time_list[i].days[j] == 1) {
if (!first) {
strcat(weekday_str, ",");
}
char tmp[8];
snprintf(tmp, sizeof(tmp), "%d", j);
strcat(weekday_str, tmp);
first = 0;
}
}
// Format time: "HH:MM" with zero padding
char start_time_str[16] = {0};
char end_time_str[16] = {0};
snprintf(start_time_str, sizeof(start_time_str), "%02d:%02d",
time_config->time_list[i].start_time.hour,
time_config->time_list[i].start_time.min);
snprintf(end_time_str, sizeof(end_time_str), "%02d:%02d",
time_config->time_list[i].end_time.hour,
time_config->time_list[i].end_time.min);
// Format: "1,2,4,5;00:00-23:59"
snprintf(time_str, sizeof(time_str), "%s;%s-%s", weekday_str, start_time_str, end_time_str);
printf("time_str: %s\n", time_str);
af_uci_add_list(uci_ctx, "appfilter.time.time", time_str);
}
} else {
// Dynamic mode: write seg_time, deny_time, allow_time
af_uci_set_int_value(uci_ctx, "appfilter.time.deny_time", time_config->deny_time);
af_uci_set_int_value(uci_ctx, "appfilter.time.allow_time", time_config->allow_time);
char start_time_str[16] = {0};
char end_time_str[16] = {0};
// Format time: "HH:MM" with zero padding
snprintf(start_time_str, sizeof(start_time_str), "%02d:%02d",
time_config->seg_time.start_time.hour,
time_config->seg_time.start_time.min);
snprintf(end_time_str, sizeof(end_time_str), "%02d:%02d",
time_config->seg_time.end_time.hour,
time_config->seg_time.end_time.min);
af_uci_set_value(uci_ctx, "appfilter.time.start_time", start_time_str);
af_uci_set_value(uci_ctx, "appfilter.time.end_time", end_time_str);
}
af_uci_commit(uci_ctx, "appfilter");
uci_free_context(uci_ctx);
}
int af_load_time_config(af_time_config_t *t_config)
{
char time_list_buf[MAX_TIME_LIST_LEN] = {0};
char days_buf[128] = {0};
char start_time_buf[128] = {0};
char end_time_buf[128] = {0};
struct uci_context *ctx = uci_alloc_context();
int old_ver_config = 0;
printf("af_load_time_config: start\n");
if (!ctx)
return -1;
memset(t_config, 0, sizeof(af_time_config_t));
t_config->time_mode = af_uci_get_int_value(ctx, "appfilter.time.time_mode");
t_config->deny_time = af_uci_get_int_value(ctx, "appfilter.time.deny_time");
t_config->allow_time = af_uci_get_int_value(ctx, "appfilter.time.allow_time");
af_uci_get_value(ctx, "appfilter.time.start_time", start_time_buf, sizeof(start_time_buf));
af_uci_get_value(ctx, "appfilter.time.end_time", end_time_buf, sizeof(end_time_buf));
af_uci_get_value(ctx, "appfilter.time.days", days_buf, sizeof(days_buf));
sscanf(start_time_buf, "%d:%d", &t_config->seg_time.start_time.hour, &t_config->seg_time.start_time.min);
sscanf(end_time_buf, "%d:%d", &t_config->seg_time.end_time.hour, &t_config->seg_time.end_time.min);
t_config->time_num = 0;
// Parse global days (may be empty, continue even if empty)
char *saveptr2 = NULL;
char *p = strtok_r(days_buf, " ", &saveptr2);
if (p) {
do {
t_config->days[atoi(p)] = 1;
printf("af_load_time_config: day[%d] = 1\n", atoi(p));
p = strtok_r(NULL, " ", &saveptr2);
} while (p != NULL);
}
af_uci_get_list_value(ctx, "appfilter.time.time", time_list_buf, sizeof(time_list_buf), " ");
printf("af_load_time_config: time_list_buf from uci: %s\n", time_list_buf);
char time_list_copy[MAX_TIME_LIST_LEN] = {0};
strncpy(time_list_copy, time_list_buf, sizeof(time_list_copy) - 1);
// Use strtok_r to avoid issues with nested strtok calls
char *saveptr1 = NULL;
p = strtok_r(time_list_copy, " ", &saveptr1);
if (!p) {
printf("af_load_time_config: no time periods found\n");
goto EXIT;
}
int period_idx = 0;
do
{
printf("af_load_time_config: parsing period[%d]: %s\n", period_idx, p);
char *time_part = p;
// Initialize days array for this time period (use global days as default)
int i;
for (i = 0; i < 7; i++) {
t_config->time_list[t_config->time_num].days[i] = t_config->days[i];
}
// Check if format is new (with weekdays): "1,2,4,5;00:00-23:59"
char *semicolon = strchr(p, ';');
if (semicolon) {
// New format: parse weekdays and store in this time period's days array
char weekday_str[64] = {0};
strncpy(weekday_str, p, semicolon - p);
weekday_str[semicolon - p] = '\0';
time_part = semicolon + 1;
printf("af_load_time_config: period[%d] has weekdays: %s, time_part: %s\n", period_idx, weekday_str, time_part);
// Clear days array for this time period first
for (i = 0; i < 7; i++) {
t_config->time_list[t_config->time_num].days[i] = 0;
}
// Parse weekdays: "1,2,4,5" using strtok_r
char weekday_copy[64] = {0};
strncpy(weekday_copy, weekday_str, sizeof(weekday_copy) - 1);
char *saveptr2 = NULL;
char *wd = strtok_r(weekday_copy, ",", &saveptr2);
while (wd) {
int day_val = atoi(wd);
if (day_val >= 0 && day_val < 7) {
t_config->time_list[t_config->time_num].days[day_val] = 1;
printf("af_load_time_config: period[%d] set day %d\n", period_idx, day_val);
}
wd = strtok_r(NULL, ",", &saveptr2);
}
} else {
LOG_WARN("af_load_time_config: period[%d] no weekdays, using global days\n", period_idx);
old_ver_config = 1;
}
// If no semicolon, use global days (already copied above)
// Parse time: "00:00-23:59" or "1,2,4,5;00:00-23:59" (time_part already points to time part)
int ret = sscanf(time_part, "%d:%d-%d:%d", &t_config->time_list[t_config->time_num].start_time.hour,
&t_config->time_list[t_config->time_num].start_time.min, &t_config->time_list[t_config->time_num].end_time.hour, &t_config->time_list[t_config->time_num].end_time.min);
if (ret != 4) {
printf("af_load_time_config: period[%d] ERROR: failed to parse time from %s\n", period_idx, time_part);
} else {
printf("af_load_time_config: time[%d] %d:%d-%d:%d, days: ", t_config->time_num, t_config->time_list[t_config->time_num].start_time.hour, t_config->time_list[t_config->time_num].start_time.min,
t_config->time_list[t_config->time_num].end_time.hour, t_config->time_list[t_config->time_num].end_time.min);
for (i = 0; i < 7; i++) {
if (t_config->time_list[t_config->time_num].days[i]) {
printf("%d ", i);
}
}
printf("\n");
t_config->time_num++;
}
period_idx++;
} while (p = strtok_r(NULL, " ", &saveptr1));
printf("af_load_time_config: total periods loaded: %d\n", t_config->time_num);
// Load mode 2 daily limit config (if time_mode is 2)
if (t_config->time_mode == 2) {
int weekday;
for (weekday = 0; weekday < 7; weekday++) {
char uci_key[64] = {0};
snprintf(uci_key, sizeof(uci_key), "appfilter.time.daily_limit_%d", weekday);
char daily_limit_str[128] = {0};
af_uci_get_value(ctx, uci_key, daily_limit_str, sizeof(daily_limit_str));
// Initialize to default values
t_config->daily_limit[weekday].enable = 0;
t_config->daily_limit[weekday].am_time = 0;
t_config->daily_limit[weekday].pm_time = 0;
// Parse format: "enable:am_time:pm_time"
if (strlen(daily_limit_str) > 0) {
char *first_colon = strchr(daily_limit_str, ':');
if (first_colon) {
char *second_colon = strchr(first_colon + 1, ':');
if (second_colon) {
// New format: "enable:am_time:pm_time"
t_config->daily_limit[weekday].enable = atoi(daily_limit_str);
t_config->daily_limit[weekday].am_time = atoi(first_colon + 1);
t_config->daily_limit[weekday].pm_time = atoi(second_colon + 1);
} else {
// Old format: "am_time:pm_time"
t_config->daily_limit[weekday].enable = 1;
t_config->daily_limit[weekday].am_time = atoi(daily_limit_str);
t_config->daily_limit[weekday].pm_time = atoi(first_colon + 1);
}
} else {
t_config->daily_limit[weekday].enable = 1;
t_config->daily_limit[weekday].am_time = atoi(daily_limit_str);
}
}
printf("af_load_time_config: daily_limit[%d] enable=%d, am_time=%d, pm_time=%d\n",
weekday, t_config->daily_limit[weekday].enable,
t_config->daily_limit[weekday].am_time, t_config->daily_limit[weekday].pm_time);
}
}
EXIT:
uci_free_context(ctx);
return old_ver_config;
}
void af_load_global_config(af_global_config_t *config){
int ret = 0;
char lan_ifname[32] = {0};
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return;
ret = af_uci_get_int_value(ctx, "appfilter.global.enable");
if (ret < 0)
config->enable = 0;
else
config->enable = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.record_enable");
if (ret < 0)
config->record_enable = 0;
else
config->record_enable = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.user_mode");
if (ret < 0)
config->user_mode = 0;
else
config->user_mode = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.work_mode");
if (ret < 0)
config->work_mode = 0;
else
config->work_mode = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.tcp_rst");
if (ret < 0)
config->tcp_rst = 1;
else
config->tcp_rst = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.disable_hnat");
if (ret < 0)
config->disable_hnat = 1;
else
config->disable_hnat = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.auto_load_engine");
if (ret < 0)
config->auto_load_engine = 0;
else
config->auto_load_engine = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.disable_quic");
if (ret < 0)
config->disable_quic = 0;
else
config->disable_quic = ret;
ret = af_uci_get_int_value(ctx, "appfilter.global.app_filter_mode");
if (ret < 0)
config->app_filter_mode = 0; // Default to specified apps mode
else
config->app_filter_mode = ret;
ret = af_uci_get_value(ctx, "appfilter.global.lan_ifname", lan_ifname, sizeof(lan_ifname));
if (ret < 0)
strncpy(config->lan_ifname, "br-lan", sizeof(config->lan_ifname) - 1);
else
strncpy(config->lan_ifname, lan_ifname, sizeof(config->lan_ifname) - 1);
uci_free_context(ctx);
LOG_DEBUG("enable=%d, user_mode=%d, work_mode=%d, disable_quic=%d, app_filter_mode=%d\n", config->enable, config->user_mode, config->work_mode, config->disable_quic, config->app_filter_mode);
}
void af_load_config(af_config_t *config){
memset(config, 0, sizeof(af_config_t));
af_load_global_config(&config->global);
if (1 == af_load_time_config(&config->time)){
apply_time_config_to_uci(&config->time);
}
}
void update_oaf_proc_value(char *key, char *value){
char cmd_buf[128] = {0};
char file_path[128] = {0};
char old_value[128] = {0};
sprintf(file_path, "/proc/sys/oaf/%s", key);
if (af_read_file_value(file_path, old_value, sizeof(old_value)) == -1)
return;
if (strcmp(old_value, value) != 0){
sprintf(cmd_buf, "echo %s >/proc/sys/oaf/%s", value, key);
system(cmd_buf);
LOG_DEBUG("update %s %s-->%s\n", key, old_value, value);
}
}
void update_oaf_proc_u32_value(char *key, u_int32_t value){
char buf[32] = {0};
sprintf(buf, "%u", value);
update_oaf_proc_value(key, buf);
}
void update_lan_ip(void){
char ip_str[32] = {0};
char mask_str[32] = {0};
struct in_addr addr;
struct in_addr mask_addr;
char cmd_buf[128] = {0};
u_int32_t lan_ip = 0;
u_int32_t lan_mask = 0;
char lan_ifname[32] = {0};
char ip_cmd_buf[128] = {0};
char mask_cmd_buf[128] = {0};
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return;
int ret = af_uci_get_value(ctx, "appfilter.global.lan_ifname", lan_ifname, sizeof(lan_ifname) - 1);
if (ret != 0){
strcpy(lan_ifname, "br-lan");
}
sprintf(ip_cmd_buf, CMD_GET_LAN_IP_FMT , lan_ifname);
sprintf(mask_cmd_buf, CMD_GET_LAN_MASK_FMT , lan_ifname);
exec_with_result_line(ip_cmd_buf, ip_str, sizeof(ip_str));
if (strlen(ip_str) < MIN_INET_ADDR_LEN){
update_oaf_proc_u32_value("lan_ip", 0);
}
else{
inet_aton(ip_str, &addr);
lan_ip = addr.s_addr;
update_oaf_proc_u32_value("lan_ip", lan_ip);
}
exec_with_result_line(mask_cmd_buf, mask_str, sizeof(mask_str));
if (strlen(mask_str) < MIN_INET_ADDR_LEN){
update_oaf_proc_u32_value("lan_mask", 0);
}
else{
inet_aton(mask_str, &mask_addr);
lan_mask = mask_addr.s_addr;
update_oaf_proc_u32_value("lan_mask", lan_mask);
}
uci_free_context(ctx);
}
int af_check_time_manual(af_time_config_t *t_config) {
time_t now = time(NULL);
struct tm *current_time = localtime(&now);
int current_minutes = current_time->tm_hour * 60 + current_time->tm_min;
int current_wday = current_time->tm_wday;
int i;
for (i = 0; i < t_config->time_num; i++) {
if (!t_config->time_list[i].days[current_wday]) {
printf("current day %d not in time[%d] days\n", current_wday, i);
continue;
}
int start_minutes = t_config->time_list[i].start_time.hour * 60 + t_config->time_list[i].start_time.min;
int end_minutes = t_config->time_list[i].end_time.hour * 60 + t_config->time_list[i].end_time.min;
printf("check time: %02d:%02d-%02d:%02d\n",
t_config->time_list[i].start_time.hour, t_config->time_list[i].start_time.min,
t_config->time_list[i].end_time.hour, t_config->time_list[i].end_time.min);
if (current_minutes >= start_minutes && current_minutes <= end_minutes) {
printf("current time in time list\n");
g_af_status.match_time = 1;
return 1;
}
}
g_af_status.match_time = 0;
return 0;
}
int af_check_time_dynamic(af_time_config_t *t_config) {
return g_af_status.filter;
}
int update_dynamic_used_time(af_time_config_t *t_config){
if (t_config->time_mode != 1)
return -1;
time_t now = time(NULL);
struct tm *current_time = localtime(&now);
if (!t_config->days[current_time->tm_wday]) {
LOG_DEBUG("current day not in configured days\n");
af_init_time_status();
return -1;
}
int current_minutes = current_time->tm_hour * 60 + current_time->tm_min;
int start_minutes = t_config->seg_time.start_time.hour * 60 + t_config->seg_time.start_time.min;
int end_minutes = t_config->seg_time.end_time.hour * 60 + t_config->seg_time.end_time.min;
LOG_DEBUG("check seg_time: %02d:%02d-%02d:%02d\n",
t_config->seg_time.start_time.hour, t_config->seg_time.start_time.min,
t_config->seg_time.end_time.hour, t_config->seg_time.end_time.min);
if (!(current_minutes >= start_minutes && current_minutes <= end_minutes)) {
LOG_DEBUG("current time not in seg_time\n");
af_init_time_status();
return 0;
}
g_af_status.match_time = 1;
if (g_af_status.filter == 1) {
g_af_status.deny_time++;
if (g_af_status.deny_time >= t_config->deny_time) {
g_af_status.filter = 0;
g_af_status.deny_time = 0;
}
} else {
g_af_status.allow_time++;
if (g_af_status.allow_time >= t_config->allow_time) {
g_af_status.filter = 1;
g_af_status.allow_time = 0;
}
}
return 0;
}
int af_check_time_period_limit(af_time_config_t *t_config) {
int total_active_time = 0;
int selected_user_count = 0;
int i;
time_t now = time(NULL);
struct tm *current_time = localtime(&now);
int current_weekday = current_time->tm_wday;
int current_hour = current_time->tm_hour;
LOG_DEBUG("check period limit mode: weekday=%d, hour=%d\n", current_weekday, current_hour);
daily_limit_config_t *daily_limit = &t_config->daily_limit[current_weekday];
if (!daily_limit->enable) {
LOG_DEBUG("Time limit not enabled for weekday %d\n", current_weekday);
g_af_status.match_time = 0;
g_af_status.remain_time = 0;
g_af_status.used_time = 0;
g_af_status.period_blocked = 0;
return 0;
}
int max_allowed_time = 0;
int is_morning = (current_hour < 12);
if (is_morning) {
max_allowed_time = daily_limit->am_time;
LOG_DEBUG("Morning period: max_allowed_time=%d\n", max_allowed_time);
} else {
max_allowed_time = daily_limit->pm_time;
LOG_DEBUG("Afternoon period: max_allowed_time=%d\n", max_allowed_time);
}
if (max_allowed_time <= 0) {
LOG_DEBUG("No time limit set for current period\n");
g_af_status.match_time = 0;
g_af_status.remain_time = 0;
g_af_status.used_time = 0;
g_af_status.period_blocked = 0;
return 0;
}
check_all_users_period_time();
for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) {
dev_node_t *node = dev_hash_table[i];
while (node) {
if (node->is_selected) {
if (is_morning) {
total_active_time += node->today_am_active_time;
LOG_DEBUG("Selected user %s (online=%d): today_am_active_time=%d, total=%d\n",
node->mac, node->online, node->today_am_active_time, total_active_time);
} else {
total_active_time += node->today_pm_active_time;
LOG_DEBUG("Selected user %s (online=%d): today_pm_active_time=%d, total=%d\n",
node->mac, node->online, node->today_pm_active_time, total_active_time);
}
if (node->online) {
selected_user_count++;
}
}
node = node->next;
}
}
g_af_status.used_time = total_active_time;
int remain_time = max_allowed_time - total_active_time;
if (remain_time < 0) {
remain_time = 0;
}
g_af_status.remain_time = remain_time;
LOG_DEBUG("Selected users count: %d, total_active_time=%d, max_allowed=%d, remain_time=%d\n",
selected_user_count, total_active_time, max_allowed_time, remain_time);
if (total_active_time >= max_allowed_time) {
g_af_status.match_time = 1;
g_af_status.period_blocked = 1;
LOG_DEBUG("Period limit mode: enable filter (total time exceeded: %d >= %d)\n",
total_active_time, max_allowed_time);
return 1;
} else {
g_af_status.match_time = 1;
g_af_status.period_blocked = 0;
LOG_DEBUG("Period limit mode: disable filter (total time: %d < %d, remain: %d)\n",
total_active_time, max_allowed_time, remain_time);
return 0;
}
}
int af_check_time_valid(af_time_config_t *t_config) {
time_t now = time(NULL);
struct tm *current_time = localtime(&now);
if (t_config->time_mode == 0) {
return af_check_time_manual(t_config);
} else if (t_config->time_mode == 1) {
return af_check_time_dynamic(t_config);
} else if (t_config->time_mode == 2) {
return af_check_time_period_limit(t_config);
}else{
return 0;
}
}
void update_oaf_status(void){
int ret = 0;
int cur_enable = 0;
if(g_af_config.global.enable == 1){
ret = af_check_time_valid(&g_af_config.time);
}
update_oaf_proc_value("enable", ret == 1 ? "1" : "0");
}
void update_oaf_record_status(void){
update_oaf_proc_value("record_enable", g_af_config.global.record_enable==1?"1":"0");
}
void update_oaf_disable_quic_status(void){
update_oaf_proc_value("disable_quic", g_af_config.global.disable_quic==1?"1":"0");
}
void update_oaf_app_filter_mode_status(void){
update_oaf_proc_value("app_filter_mode", g_af_config.global.app_filter_mode==1?"1":"0");
}
int af_nl_clean_feature(void){
af_msg_t msg;
if (appfilter_nl_fd.fd < 0){
return -1;
}
msg.action = AF_MSG_CLEAN_FEATURE;
send_msg_to_kernel(appfilter_nl_fd.fd,(void *)&msg, sizeof(msg));
return 0;
}
int af_nl_add_feature(char *feature){
char msg_buf[1024] = {0};
if (appfilter_nl_fd.fd < 0){
return -1;
}
char *p_data = msg_buf + sizeof(af_msg_t);
memset(msg_buf, 0, sizeof(msg_buf));
af_msg_t *hdr = (af_msg_t *)msg_buf;
hdr->action = AF_MSG_ADD_FEATURE;
strncpy(p_data, feature, strlen(feature));
send_msg_to_kernel(appfilter_nl_fd.fd,(void *)msg_buf, sizeof(af_msg_t) + strlen(feature) + 1);
return 0;
}
int af_load_feature_to_kernel(void){
char line_buf[MAX_FEATURE_LINE_LEN] = {0};
FILE *fp = fopen("/tmp/feature.cfg", "r");
if (!fp)
{
printf("open file failed\n");
return -1;
}
if (af_nl_clean_feature() < 0){
return -1;
}
while (fgets(line_buf, sizeof(line_buf), fp))
{
str_trim(line_buf);
if (strlen(line_buf) < 8)
continue;
if (strstr(line_buf, "#"))
continue;
if (strlen(line_buf) >= MAX_FEATURE_LINE_LEN - 1){
continue;
}
af_nl_add_feature(line_buf);
}
fclose(fp);
return 0;
}
int reload_feature(void){
system("gen_class.sh /tmp/feature.cfg");
init_app_name_table();
init_app_class_name_table();
if (af_load_feature_to_kernel() < 0){
LOG_ERROR("Failed to load feature to kernel\n");
return -1;
}
clean_invalid_app_records();
clear_device_app_statistics();
LOG_WARN("reload feature success\n");
g_feature_update_time = get_timestamp();
return 0;
}
void check_date_change(void)
{
static int last_day = -1;
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
int current_day = tm_info->tm_mday;
if (last_day != current_day )
{
LOG_WARN("day changed: %d -> %d\n",last_day, current_day);
if (last_day != -1){
clear_device_app_statistics();
reset_all_users_today_active_time();
reset_all_users_today_flow();
}
last_day = current_day;
}
}
void oaf_timeout_handler(struct uloop_timeout *t)
{
static int count = 0;
if (count % 10 == 0){
update_dev_list();
update_oaf_status();
}
if (count % 60 == 0){
LOG_DEBUG("begin check dev count = %d\n", count);
check_dev_visit_info_expire();
flush_expire_visit_info();
update_dynamic_used_time(&g_af_config.time);
update_oaf_status();
update_lan_ip();
if (check_dev_expire()){
flush_dev_expire_node();
}
check_date_change();
check_all_users_period_time();
dump_dev_list();
}
if (count % 300 == 0 && count > 0 && g_af_config.time.time_mode == 2){
save_user_time_to_file();
}
if (g_oaf_config_change == 1){
LOG_WARN("config changed\n");
update_lan_ip();
af_load_config(&g_af_config);
update_dev_selected_flag();
update_dynamic_used_time(&g_af_config.time);
update_oaf_status();
update_oaf_record_status();
update_oaf_disable_quic_status();
update_oaf_app_filter_mode_status();
g_oaf_config_change = 0;
}
if (appfilter_nl_fd.fd < 0 && access("/proc/sys/oaf", F_OK) == 0){
appfilter_nl_fd.fd = appfilter_nl_init();
if (appfilter_nl_fd.fd > 0){
uloop_fd_add(&appfilter_nl_fd, ULOOP_READ);
system("oaf_rule reload &");
LOG_INFO("netlink connect success\n");
}
}
if (g_feature_update == 1 && appfilter_nl_fd.fd > 0){
if (0 == reload_feature()){
g_feature_update = 0;
}
}
count++;
uloop_timeout_set(t, 1000);
}
void af_load_engine(void){
if (g_af_config.global.auto_load_engine == 1){
if (access("/lib/modules/oaf.ko", F_OK) == 0) {
system("insmod /lib/modules/oaf.ko");
LOG_WARN("insmod /lib/modules/oaf.ko");
} else {
system("modprobe oaf");
LOG_WARN("modprobe oaf");
}
}
else{
LOG_WARN("auto load disabled, not load oaf.ko\n");
}
}
void handle_sigusr1(int sig) {
LOG_WARN("Received SIGUSR1 signal\n");
g_feature_update = 1;
}
void handle_sigusr2(int sig) {
LOG_INFO("Received SIGUSR2 signal\n");
if (current_log_level >= LOG_LEVEL_ERROR)
current_log_level = LOG_LEVEL_DEBUG;
else
current_log_level++;
LOG_WARN("change log level to %d\n", current_log_level);
}
int main(int argc, char **argv)
{
int ret = 0;
LOG_INFO("appfilter start");
g_feature_update = 1;
af_load_config(&g_af_config);
af_load_engine();
af_init_status();
uloop_init();
signal(SIGUSR1, handle_sigusr1);
signal(SIGUSR2, handle_sigusr2);
signal(SIGCHLD, SIG_IGN);
init_dev_node_htable();
load_user_time_from_file();
if (appfilter_ubus_init() < 0)
{
LOG_ERROR("Failed to connect to ubus\n");
return 1;
}
appfilter_nl_fd.fd = -1;
uloop_timeout_set(&dev_tm, 5000);
uloop_timeout_add(&dev_tm);
uloop_run();
uloop_done();
return 0;
}
+107
View File
@@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/time.h>
char *str_trim(char *s) {
char *start, *last, *bk;
int len;
start = s;
while (isspace(*start))
start++;
bk = last = s + strlen(s) - 1;
while (last > start && isspace(*last))
last--;
if ((s != start) || (bk != last)) {
len = last - start + 1;
strncpy(s, start, len);
s[len] = '\0';
}
return s;
}
int exec_with_result_line(char *cmd, char *result, int len)
{
FILE *fp = NULL;
if (!cmd || !result || !len)
return -1;
fp = popen(cmd, "r");
if (!fp)
return -1;
fgets(result, len, fp);
str_trim(result);
pclose(fp);
return 0;
}
unsigned int get_timestamp(void)
{
struct timeval cur_time;
gettimeofday(&cur_time, NULL);
return cur_time.tv_sec;
}
int check_same_network(char *ip1, char *netmask, char *ip2) {
struct in_addr addr1, addr2, mask;
if (inet_pton(AF_INET, ip1, &addr1) != 1) {
printf("Invalid IP address: %s\n", ip1);
return -1;
}
if (inet_pton(AF_INET, netmask, &mask) != 1) {
printf("Invalid netmask: %s\n", netmask);
return -1;
}
if (inet_pton(AF_INET, ip2, &addr2) != 1) {
printf("Invalid IP address: %s\n", ip2);
return -1;
}
if ((addr1.s_addr & mask.s_addr) == (addr2.s_addr & mask.s_addr)) {
return 1;
} else {
return 0;
}
}
int af_read_file_value(const char *file_path, char *value, int value_len) {
FILE *file = fopen(file_path, "r");
if (!file) {
//perror("Failed to open file");
return -1;
}
if (fgets(value, value_len, file) == NULL) {
perror("Failed to read line from file");
fclose(file);
return -2;
}
size_t len = strlen(value);
if (len > 0 && value[len - 1] == '\n') {
value[len - 1] = '\0';
}
fclose(file);
return 0;
}
int af_read_file_int_value(const char *file_path, int *value) {
char line_buf[128] = {0};
if (af_read_file_value(file_path, line_buf, sizeof(line_buf)) < 0){
return -1;
}
*value = atoi(line_buf);
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef __UTILS_H__
#define __UTILS_H__
char *str_trim(char *s);
int exec_with_result_line(char *cmd, char *result, int len);
int check_same_network(char *ip1, char *netmask, char *ip2);
int af_read_file_value(const char *file_path, char *value, int value_len);
int af_read_file_int_value(const char *file_path, int *value);
unsigned int get_timestamp(void);
#endif