特色文章

客厅折腾系列

深圳福田,家里用的是深圳电信的IPTV+宽带,从光猫千兆网口有线到路由器拨号,从光猫iTV接口到机顶盒拨号,机顶盒HDMI连接到电视机播放IPTV,但是视频播放就非常的麻烦。

最近,大家都在抓IPTV的视频源,使用OpenWrt的udpxy做内网融合,实现家里的每一个设备都能看IPTV,在OpenWrt使用https://github.com/messense/aliyundrive-webdav挂载阿里云盘,在电视机安装Kodi播放高清视频。

但是,问题在于电视机广告众多,安装在电视机的Kodi解码能力弱,于是在网上找了e900v22c机顶盒安装CoreELEC跑Kodi,把IPTV源引入到Kodi,实现高清家庭影院+IPTV。

这里面涉及到OpenWrt的配置,IPTV的上行IPOE认证抓包,下行IPTV源抓包,CoreELEC的刷机配置,各个部分都有很多小技巧,于是做一个完整的记录。

  1. 路由器更换 | Bigtan’s Blog
  2. 原生OpenWrt编译 | Bigtan’s Blog
  3. IPTV抓包 | Bigtan’s Blog
  4. e900v22c刷CoreELEC | Bigtan’s Blog

OpenWrt的UPnP失效分析及解决

原生OpenWrt的UPnP一直时好时不好,今天花了一些时间,好好研究了一下中间的原理;

首先,打开UPnP的调试日志,观察到报错的部分:

UPnP试图绑定的interface是我的IPTV接口,并且识别到是一个内部ip,所以无法绑定成功。

以此看upnp进程:

/usr/sbin/miniupnpd -f /var/etc/miniupnpd.conf

发现了问题,UPnP生成的配置文件里面看到IPv4的出口错误的指向了我的IPTV拨号接口

ext_ifname=lan1
ext_ifname6=pppoe-wan

这个配置文件的路径是软链接到tmp的,那么这个文件应该是动态生成的,没法直接修改。

/etc/init.d/miniupnpd

找到了UPnP的启动脚本在这里,那么找到127-128行有这个字段的赋值,明显是他寻找出口的逻辑在我的双wan拨号下不适用,那么我就适用了一个简单的办法,把IPv4的接口也指向IPv6,反正IPv6是对的,简单的先解决这个问题。如果是更复杂的场景,把ifname写死即可。

echo "ext_ifname=$ifname6"
echo "ext_ifname6=$ifname6"

到这里,UPnP终于是可以正常工作了。

在OpenWrt使用DNSPod提供的DDNS服务

增加Providor

wget https://cdn.jsdelivr.net/gh/openwrt/packages/net/ddns-scripts/files/usr/share/ddns/default/dnspod.cn.json -O /usr/share/ddns/default/dnspod.cn.json
wget https://cdn.jsdelivr.net/gh/openwrt/packages/net/ddns-scripts/files/usr/lib/ddns/update_dnspod_cn.sh -O /usr/lib/ddns/update_dnspod_cn.sh

在OpenWrt正常配置DDNS即可

e900v22c刷CoreELEC

e900v22c

这个设备本身是移动的机顶盒,因为配置比较好,还能刷机,被开发成了CoreELEC的盒子,闲鱼随便买,几十块钱。

1下载镜像

配置好的地址:https://github.com/KryptonLee/e900v22c-CoreELEC

官方地址:https://github.com/CoreELEC/CoreELEC

2.制作U盘映像

映像工具:https://sourceforge.net/projects/win32diskimager/

3.从U盘启动

插入U盘,上电,一直按遥控器的右方向键,进入U盘引导

4.写入EMMC

配置打开SSH,默认密码是coreelec,用如下命令刷写内部存储:

ceemmc -x

具体启动方式的选择看console的提示即可

IPTV抓包

IPTV抓包,我用的是Throwing Star LAN Tap这个设备

从网上找的图,j3可以抓到上行流量包,j4可以抓到下行流量包

流量包分析

1.上行流量包分析

上行主要是抓IPOE的鉴权信息,参考:https://v2ex.com/t/896669

关键步骤摘录如下:

 interface 'IPTV'
	option proto 'dhcp'
	option macaddr 'aa:bb:cc:dd:ee:ff'
	option delegate '0'
	option metric '20'
	option hostname 'HOSTNAME'
	option device 'lan1'
	option sendopts '0x37:01792103060c0f1a1c2a33363a3b77'
	option vendorid 'VENDORID'
  • aa:bb:cc:dd:ee:ff 修改为你机顶盒的 MAC 地址 也就是上图抓包中显示的 Client MAC address
  • HOSTNAME 修改为上图抓包中显示的 option 12 内容,形如00123456789AABBCCDDEEFF
  • VENDORID 为上图中 option 60 的内容,如果此内容包含非 ASCII 字符,需要在 Wireshark 中以原始数据查看,并粘贴在此处。
  • 0x37:01792103060c0f1a1c2a33363a3b77 这一行对应抓包图中 option 55 ,其中 0x37 即为 55 的 16 进制表述

如果 option 60 ,即 Vendor Class 填入的是 ASCII 字符,则不需要进行此部分操作。

修改文件:

/lib/netifd/proto/dhcp.sh

找到此行:

${vendorid:+-V "$vendorid"} \

修改为:

${vendorid:+-V "" "-x 0x3c:$vendorid"}

保存文件,重启端口即可。

2.下行流量包分析

下行主要是抓IPTV源信息,参考:https://www.right.com.cn/FORUM/thread-4177713-1-1.html

路由器配置

首先配置IPOE拨号,然后把IPTV源用udpxy引入内网,网上教程很多,随便贴一个:https://zhuanlan.zhihu.com/p/500324081

原生OpenWrt编译

对于开源系统,我一向是喜欢自己编译,不喜欢用别人的系统,这里记录一下给AX6s编译原生OpenWrt系统。

配置Ubuntu用户

sudo useradd -r -m -s /bin/bash lede
sudo passwd lede

修改/etc/sudoers文件:

编译配置

sudo apt update
sudo apt install build-essential clang flex g++ gawk gcc-multilib gettext \
git libncurses5-dev libssl-dev python3-distutils rsync unzip zlib1g-dev \
file wget

克隆源码,签出指定标签

git clone https://github.com/openwrt/openwrt
cd openwrt/
git checkout -b v22.03.2
./scripts/feeds update -a
./scripts/feeds install -a
make menuconfig

配置时,有几个需要注意的:

  1. Dnsmasq最好是换成Dnsmasq-full
  2. QoS,使用nft-qos包,因为新的OpenWrt里面的iptables已经全部升级为nftables

后面就是正常刷入AX6s即可。

路由器更换

运营商送的是华为的路由器,这个路由器性能还是不错,但是可玩性不足,于是购入了红米AX6s,刷入OpenWrt,来跑一些服务。

下面记录一下OpenWrt的刷入过程:

升级OpenWrt

1.升级开发版固件

登录红米 AX6S 的后台(一般是:192.168.31.1),点击右上角选择-系统升级-选择手动升级,勾选下载好的「内测版」固件,点击开始升级。

2.计算SSH密码

#!/usr/bin/env python3
import sys
import hashlib

if sys.version_info < (3,7):
    print("python version is not supported", file=sys.stderr)
    sys.exit(1)

# credit goes to zhoujiazhao:
# https://blog.csdn.net/zhoujiazhao/article/details/102578244

salt = {'r1d': 'A2E371B0-B34B-48A5-8C40-A7133F3B5D88',
        'others': 'd44fb0960aa0-a5e6-4a30-250f-6d2df50a'}


def get_salt(sn):
    if "/" not in sn:
        return salt["r1d"]

    return "-".join(reversed(salt["others"].split("-")))


def calc_passwd(sn):
    passwd = sn + get_salt(sn)
    m = hashlib.md5(passwd.encode())
    return m.hexdigest()[:8]


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <S/N>")
        sys.exit(1)

    serial = sys.argv[1]
    print(calc_passwd(serial))

3.telnet 连接开启 ssh

用root和计算得到的密码telnet上去,输入以下代码:

nvram set ssh_en=1 & nvram set uart_en=1 & nvram set boot_wait=on & nvram set bootdelay=3 & nvram set flag_try_sys1_failed=0 & nvram set flag_try_sys2_failed=1
nvram set flag_boot_rootfs=0 & nvram set "boot_fw1=run boot_rd_img;bootm"
nvram set flag_boot_success=1 & nvram commit & /etc/init.d/dropbear enable & /etc/init.d/dropbear start

4.SSH上去刷入底包

cd /tmp
curl -L https://sebs.oss-cn-shanghai.aliyuncs.com/factory.bin -o factory.bin
mtd -r write /tmp/factory.bin firmware

当然,我是自己编译的原生OpenWrt,这个后面写文章单独说。

配置阿里云

参考https://github.com/messense/aliyundrive-webdav即可

子主题持久化修改

我的WordPress博客一直用的官方的这个非常古老的主体twentytwelve,但是一直有做一些修改:

  • 去掉所有a标签的下划线
  • 修改脚注上的Powered by WordPress为备案信息
  • 将gravatar的url地址重写到自己的cdn上

为了持久化这些修改,同时能够保证WordPress自动升级后不失效,我采用了官方推荐的子主题方式来做修改:

  1. 新建一个子主题twentytwelve-child
  2. 新建一个style.css,导入父主体的css,然后修改a标签去掉下划线
  3. 新建一个footer.php,复制父主题的footer.php,修改Powered by WordPress为备案信息
  4. 新建一个functions.php,增加一个函数,用WordPress钩子,替换原来的get_avatar函数,参考此篇文章
  5. 然后增加了一个screenshot.png,这个是可有可无的

这样下来,对WordPress自带主题的持久化修改就好了,WordPress自动升级也不会破坏这些修改,比源码强多了。