天津移动 IPTV 源的播放列表,好久以前整理过一次,最近发现好多频道失效了,重新整理并记录下来。希望能帮到有需要的人。

  记忆太久远,有些记不清了,大致是移动盒子的设置里面有个优盘抓日志还是开机抓网络日志之类的,勾上那个插上优盘,然后重启就有几率可以抓到频道列表。

扫描获取组播源

  这种方法适合没有 IPTV 盒子或没开通 IPTV 业务但知道组播 IP 段的情况。我这边不管开没开通 IPTV,IPTV 的网络配置都会下发到光猫,在路由器上设置好组播代理,路由器下的设备就可以看组播了。
  用组播还可以看 IPTV 盒子内的付费频道,没有时间限制。

扫描

  抓到的列表不是很好用,所以还是通过这个列表获取到移动的组播IP段,然后扫一下全部的频道。
  用的是 iptv_channel_scanner_windows ,有 Windows 版和 Linux 版。

1
2
iptvscanner 225.2.1.1 225.2.1.254
iptvscanner 239.0.2.1 239.0.2.254

  扫完之后会把扫描结果保存到当前目录的 m3u 文件。

节目信息和排序

  这是最枯燥无聊的步骤了,要一个一个观看列表中的频道并加上正确的频道名再按自己的喜好进行分类和排序。这里用到的工具是 PlaylistEditorTV

  EPG 用的是 https://epg.112114.xyz/,但这个网站移动访问不了,要开代理才能访问。

播放列表

移动IPTV2024-01-10.m3u
移动IPTV2024-01-10.txt

另附电信的组播列表:
电信IPTV2023-10-18.m3u
电信IPTV2023-10-18.txt

单播源,时移源及 EPG 获取

  扫出来的都是组播源,如果还想要时移和官方的 EPG 就要对 IPTV 盒子下手了。(关于移动 IPTV 盒子的更多研究还可以看这个。)

准备

  路由器下虽然可以看组播,但是不能直接访问 IPTV 的内网,需要做些设置。

如果光猫是路由模式

  如果光猫是路由模式的话,可以在路由器上用 iptables 把所有来自盒子(192.168.1.111)的 tcp 连接都转到电脑上的 Fiddler(192.168.1.2:8888) 。

  • 光猫添加路由

    ip route add default via 10.166.0.1 dev nbif1 table table.csp_main

  10.166.0.1OTHER_R_VID_xx 连接的网关,nbif1 是所在的网卡名。但是这个命令会在光猫重启后失效,每次都要去执行一次。

  • 光猫设置端口转发

    iptables -t nat -I PREROUTING -s 192.168.1.111 -p tcp -j DNAT --to-destination 192.168.1.2:8888

如果 INTERNET 是桥接,OTHER 是路由模式

  宽带桥接的话要在光猫和路由器上添加下路由才能在路由器下访问移动的 IPTV 网络。

  • 光猫添加路由

    ip route add default via 10.166.0.1 dev nbif1 table table.csp_main

  • 路由器设置路由

接口 目标 网关
wan 10.206.0.0/16 192.168.3.1
wan 10.128.0.0/24 192.168.3.1

  接口是路由器可以访问到光猫的接口,目标地址是抓盒子发的包发现的,网关就是光猫的 IP。

  这样就可以在路由器下访问 IPTV 网络了。

INTERNET 和 OTHER 都改成桥接模式

  这种方法的好处是只要有光猫的管理员密码就可以了。不用开光猫的 telnet,也不用在每次重启光猫后都去添加路由。
  把 INTERNET OTHER 都设置为桥接,改前记得记下 VLAN ID 组播VLAN 和拨号的用户名密码。
  设置完桥接后在光猫上设置好 VLAN 绑定。
  OpenWrt 上设置好 internetIPTV 接口:

名称 协议 设备
internet PPPoE wan.10
IPTV DHCP客户端 wan.30
wan DHCP客户端 wan

  OpenWrt 使用 VLAN 的方式是在网卡名后加上 .VLANID,如:wan.10wan.30。所以新建接口的设备那里也要这样填。

  • 路由器添加路由
接口 目标 网关
IPTV 10.206.0.0/16 10.166.0.1
IPTV 10.128.0.0/24 10.166.0.1

  目标地址是抓盒子的包发现的,网关就是 IPTV 接口的网关。

  这样就可以在路由器下访问 IPTV 网络了。

抓包

  在路由器上把盒子发出的 tcp 请求转到电脑上的 Fiddler ,这个也可以用来劫持盒子应用商店的下载链接来装第三方的 apk 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/sbin/nft -f
table inet nat {
chain prerouting {
type nat hook prerouting priority -30;
meta nfproto ipv4 ether saddr "盒子的mac" tcp dport 0-65535 counter dnat ip to 10.0.0.2:8888
meta nfproto ipv6 ether saddr "盒子的mac" tcp dport 0-65535 counter dnat ip6 to [fe80::abcd]:8888
}
chain postrouting {
type nat hook postrouting priority -30;
meta nfproto ipv4 ether saddr "盒子的mac" ip daddr 10.0.0.2 counter masquerade
meta nfproto ipv6 ether saddr "盒子的mac" ip6 daddr [fe80::abcd] counter masquerade
}
}

10.0.0.2 [fe80::abcd] 8888 就是电脑的 IPv4地址 IPv6地址Fiddler 的端口

节目源

  重启盒子,开机后可以看到有一条去/EPG/jsp/getchannellistHWCTC.jsp的连接,点开后就是播放地址了。

EPG 节目单

  换台时可以看到一条去 http://10.206.254.12:4000/pub/json/2023-12-31/30001110000000000000000000001343_calibrated.js?_t=1703995562326 的连接

  2023-12-31是 EPG 的日期,最多可以获取到前面三年到后面七天的节目信息。1703995562326则是当前的 13位Unix时间戳,没有这个也会返回结果。

  那30001110000000000000000000001343从哪里来呢?

  通过搜索可以找到 http://10.128.0.9:8087/IPTV-Interfaces/tianjinmobile/tv/queryChannels?extra={"spCode":"gd"}&devicestbid=9XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4&requestUuid=1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX5 点开是 JSON 格式,是里面的channelId,里面还可以看到频道名称。

  这两个链接都没有鉴权验证,组装一下就可以爬下来了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"code": "0000",
"desc": "成功",
"data": [{
"channelNo": "1",
"channelId": "30001110000000000000000000000102",
"channelName": "天津卫视高清",
"channelCode": ""
}, {
...
...
...
}, {
"channelNo": "902",
"channelId": "30001110000000000000000000001042",
"channelName": "902频道",
"channelCode": ""
}]
}

自动抓取

  之后就可以按照抓包信息,写一个模拟盒子自动登录获取频道列表和 EPG 的脚本,然后生成标准列表供 kodi emby 之类的软件订阅。

  可是其中有 AuthenticatortempKey 参数不知道是怎么生成的。左搜搜又搜搜,搜到恩山上的帖子和这篇文章

  Authenticator 是用盒子设置里的登录密码使用 3DES ECB PKCS7 加密生成的,加密前为 随便8位数字+$+TOKEN+$+USERID+$+STBID+$+IP地址+$+MAC地址+$$+CTC

  • TOKEN可以在访问 /EPG/jsp/authLoginHWCTC.jsp 时得到。
  • STBIDmac 可以从盒子下面的贴纸中找到。
  • USERID 是盒子设置里的登录帐号,登录帐号和密码一般和宽带拨号帐号密码一样,如果不同可以用 ZTE_STB_Tools 连上盒子,然后导出配置查看。
  • CTC 应该是运营商吧,但我的是移动,抓包得到的值却是CU

  测试后 ip 和 mac 为空也可以获取SessionID,抓到频道列表。

 tempKey 就没有办法了,只知道是根据 SessionID 算出来的,把服务器返回的 SessionID 修改成 11111111111111111111111111111111tempKey 会变成 BC5F5F820458CFBA981CF0C90CA313F9 ,去 cmd5 查了下结果为 781943957。实在看不出来这些有什么关系……但不传 tempKey 也可以获取到频道列表。

半成脚本

  脚本写到一半,突然觉得没有回看又不是不能看,网上的 EPG 又不是不能用,算了,就先这样吧。
  只写到获取频道列表,会存在当前目录的 iptvlist.txt 里。

getchannellist.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash

# 机顶盒帐号和密码
userid=
passwd=
# stbid ctc
stbid=
ctc=CU
# 机顶盒型号和固件版本
STBType=B860AV2.1-A
STBVersion=V81011354.5017

#ip=127.0.0.1
#mac='FF:FF:FF:FF:FF:FF'

ua='Mozilla/5.0 (Linux; Android 4.4.2; B860AV2.1-A Build/KOT49H) (ztebw,1.0.1,ZTE,blink,7105)AppleWebKit/537.36 (KHTML, like Gecko) Chrome Safari/537.36'


header="-H User-Agent: $ua"

curl -Ss "$header" -D headers.txt "http://10.206.249.8:8082/EDS/jsp/AuthenticationURL?UserID=$userid&Action=Login"

newurl=$(sed -En 's/Location: (http.+Login).+/\1/p' headers.txt)
EPGIP_PORT=$(grep -oP '(?<=EPGIP_PORT=")(.+?)(?=";)' headers.txt)

token=$(curl -Ss "$header" -X POST \
-d "UserID=$userid&VIP=" http://$EPGIP_PORT/EPG/jsp/authLoginHWCTC.jsp | \
grep -Po '(?<=var EncryptToken = ")(.+?)(?=";)')

text='12345678$'$token'$'$userid'$'$stbid'$'$ip'$'$mac'$$'$ctc
key=$passwd
key_hex=$(echo -n $key|xxd -p -c0)
auth=$(echo -n $text | openssl enc -e -des-ede3-ecb -K $key_hex 2>/dev/null | xxd -p -u -c0)

authpage=$(curl -Ss -X POST "$header" -D headers.txt \
-d "UserID=$userid&Lang=0&SupportHD=1&NetUserID=&Authenticator=$auth&STBType=$STBType&STBVersion=$STBVersion&conntype=dhcp&STBID=$stbid&templateName=&areaId=&userToken=$token&userGroupId=&productPackageId=-1&mac=$mac&UserField=0&SoftwareVersion=$STBVersion&IsSmartStb=0&desktopId=&stbmaker=&XMPPCapability=&ChipID=&VIP=" \
http://$EPGIP_PORT/EPG/jsp/ValidAuthenticationHWCTC.jsp)

cookie=$(grep 'Cookie: ' headers.txt|sed 's/Set-//')
UserToken=$(echo "$authpage" | grep -oP '(?<=name="UserToken" value=")(.+?)(?=">)')

listpage=$(curl -Ss -X POST "$header" \
-d "conntype=dhcp&UserToken=$UserToken&SupportHD=1&Lang=1" \
-H "$cookie" \
http://$EPGIP_PORT/EPG/jsp/getchannellistHWCTC.jsp)

channel=$(echo "$listpage" | grep "Authentication.CTCSetConfig('Channel','"|grep -Ev '购|聚鲨环球|食全食美|天视家居|天视优选|天视商城|天视好物|津彩生活|津彩潮流')

echo "$channel" > getchannellist.txt
echo "$channel" |sed -En 's|^.+,ChannelName="(.+)",.+,ChannelURL="igmp://(.+:[0-9]+)",TimeShift.*$|\1,rtp://\2|p' > iptvlist.txt