广东电信 IPTV 单线复用以及 openwrt 实现 IPTV 源代理

发表于 2022-06-07   |   分类于 默认分类   |   访问: 9,675 次

背景

上文中提到了广东电信的 IPTV 验证过程。虽然知道了验证方法,并且实现了自动提取频道列表,但是由于提取的 rtsp 链接是带验证而且有过期时间的,所以需要定期手动给直播软件更新源。某些直播软件能使用在线源,但是很多是不行的,这就很麻烦了。于是写了一个小程序实现 IPTV 源代理,每天自动刷新源。

IPTV 专线

PPPoE 拨号

首先需要让 IPTV 走专线,不干扰互联网链接。首先需要在路由器进行 IPTV 专线拨号。广东电信的 IPTV 是 VLAN ID 为 45 的 PPPoE 验证。在 Openwrt 中直接创建 iface.45 的接口既可以让 PPPoE 在 VLAN 45 上拨号。但是这里发现,如果已经拨号了互联网,即 VLAN 41 的 PPPoE 拨号,IPTV 拨号会失败。这是因为 MAC 地址和互联网拨号相同,需要给 VLAN 45 的虚拟接口设置另一个 MAC 地址。拨号之后可以获得一个内网地址。

这里给出配置示例,实际上在 luci 中手动添加适配即可:

config device
        option type '8021q'
        option ifname 'enp4s0f1'
        option vid '45'
        option name 'enp4s0f1.45'
        option macaddr '12:34:56:78:9A:BC' # 这里跟 WAN 不一样即可

路由

然后需要让 IPTV 的 IP 走 IPTV 接口。然后可以配置静态路由:

config route
        option interface 'iptv'
        option target '202.105.0.0/16'

config route
        option interface 'iptv'
        option target '183.59.0.0/16'

config route
        option interface 'iptv'
        option target '125.88.52.0/24'

config route
        option interface 'iptv'
        option target '59.37.208.0/24'

这里我的互联网接口叫 wan,IPTV 的接口叫 iptv。根据实际情况修改即可。至于分流的 IP 段可以自己用提取的 rtsp 链接跑跑看,然后确定出来的 302 目标。

UPnP

创建 IPTV 拨号之后我才发现,我的 miniupnp 坏掉了,原来是因为 miniupnp 跑去用 iptv 的接口当外网接口了,然后发现是内网 IP 就凉了。
修复很简单,手动改 upnp 的 wan 的接口:

config upnpd 'config'
        option external_iface 'wan'

这里我使用 upnpclient 进行测试。

IPTV 代理

由于爬出来的 RTSP 链接有期限,所以这里使用写了个 rust 程序验证 IPTV 账号,爬取链接,缓存起来,开一个简单的 RTSP 服务,然后把所有请求 302 过去真实目标。
具体逻辑如下:

  1. 监听端口 192.168.1.1:7878
  2. 播放器请求 rtsp://192.168.1.1:7878/{id}
  3. 服务器验证 IPTV 账号,获取频道列表,检查频道 ID 为 {id} 的频道的真实 RTSP 链接
  4. 服务器返回 302,让播放器跳转到真实 RTSP 链接
  5. 播放器播放真实 RTSP 链接

这样下来,只要频道 ID 是稳定的,那就能让局域网的播放器始终使用 rtsp://192.168.1.1:7878/{id} 链接,然后就能获取最新的有效的 RTSP 播放地址了。另外为了避免转台就获取频道列表,可以懒加载频道列表并且缓存起来,一天更新一次。
这里开源了一个实现 https://github.com/yujincheng08/rust-iptv-proxy ,编译(README 有 x86_64 的 openwrt 编译的方法)之后放到 openwrt 下,提供账号密码 MAC 地址和监听地址即可。至于 IPTV 频道列表导出(比如要导出 m3u 文件导入到播放器),可以改改 https://github.com/yujincheng08/tellyget-gd ,把输出链接成 rtsp://{bind_addr}/{channel_id} 即可。

已有 6 条评论


  1. Ratel

    Openwrt感觉有点难用,本来准备用N1当旁路,直接给我劝退了

    Ratel  June 9th, 2022 at 04:32 pm回复
  2. 鲁鲁

    看不懂啊能不能能不能给分解下步骤操作理由,多截图,配置看不懂

    鲁鲁  July 17th, 2022 at 10:17 pm回复
  3. DrLingCN

    可以把2个GitHub上的代码发布到openwrt的源里面再配上luci给大家直接安装使用吗?感觉缺少编译方法,不大方便自己编译呀。

    DrLingCN  July 23rd, 2022 at 01:57 am回复
  4. Mrpan

    rstp地址可以回放吗

    Mrpan  September 4th, 2022 at 02:04 pm回复
  5. cunhan

    折腾了大半天,终于把rust-iptv-proxy弄到openwrt上了。

    记录下自己遇到的问题吧

    项目默认编译出来会调用openssl3,但是openwrt只能安装到1.1.1。参考这位https://blog.xco.moe/posts/rust_build_musl/的方法,修改toml配置,绕开openssl不用了,使用rustls。 编译windows和liunx版本都很顺利,但是在交叉编译openwrt版本时,遇到这样的错误
    in function getrandom::util_libc::open_readonly': iptv.e617545e38d797b5-cgu.00:(.text._ZN9getrandom9util_libc13open_readonly17hd196f13453a759a7E+0x18): undefined reference toopen64'
    从字面上看就是生成随机数的库缺失(?),没想到解决方案的我,直接删掉rand相关的代码,那个随机整数直接写死一个大整数,又把这问题躲过去。 第3个问题是关于直播源的,git里取得ChannelUrl是“igmp|rtsp”两种地址合并的格式无法直接使用,改用TimeShiftUrl里的地址就可以。

    最后,如果README里写的编译方法看不懂的新手网友,先去找Openwrt固件编译的教程(例如https://blog.topstalk.com/%E9%9B%B6%E5%9F%BA%E7%A1%80%E7%BC%96%E8%AF%91openwrt%E7%9C%8B%E8%BF%99%E4%B8%80%E7%AF%87%E5%B0%B1%E5%A4%9F%E4%BA%86/),动手编译一个默认配置的固件就懂了。

    cunhan  October 14th, 2023 at 05:02 pm回复
  6. cunhan

    tellyget-gd的README还需要改一下,用pip install会安装原版的tellyget,原版用加密和配置之类的都不适配gd。

    cunhan  October 15th, 2023 at 10:11 am回复

发表新评论

© 2023 Powered by Typecho & Theme Quark
粤ICP备17055048号