H2-2光猫配置IPv6防火墙

1. 背景

IPv6相比IPv4的一大优势是IP地址空间充足。以笔者的中国移动宽带为例,光猫可以从运营商处获得2409开头的/64公网网段,连接至光猫的设备可自动获得公网IPv6地址:

笔者家庭网络架构

但处于安全考虑,光猫的IPv6防火墙会默认禁用所有入站连接,导致其它公网设备无法直连光猫防火墙内部的设备:

光猫入站防火墙

幸运的是,笔者使用的中国移动H2-2光猫在网上有大量使用教程,可以通过配置IPv6防火墙的方式解决这个问题。

2. 开启光猫telnet功能

  • 用普通账号登录光猫管理后台(http://192.168.1.1/),可以看到非常简陋的配置界面。

  • 此时可以手动跳转至telnet设置界面(http://192.168.1.1/getpage.gch?pid=1002&nextpage=tele_sec_tserver_t.gch),开启光猫的telnet功能。

    • 勾选“启用Telnet”,点击确定保存

    • 然后勾选“启用LAN侧Telnet”,再次点击确定保存

  • 在Chrome浏览器控制台中运行document.getElementById("Frm_TSPassword").type = "text"命令可显示telnet密码。

    • 不过好像所有的H2-2光猫telnet密码都是aDm8H%MdA,且无法通过这个页面更改

  • 在本机命令行中运行telnet命令即可登录至光猫,并通过su命令获取root权限:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ~ telnet 192.168.1.1
    Trying 192.168.1.1...
    Connected to 192.168.1.1.
    Escape character is '^]'.

    Login: CMCCAdmin
    Password:
    ~ $ su
    Password:
    / #

3. 自动登录telnet脚本

考虑到telnet登录比较繁琐,所以笔者编写了一个expect[1]脚本,用于自动登录光猫:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 ~ cat ~/scripts/telnet_modem
#!/usr/bin/env expect
set timeout 5
set host "192.168.1.1"
set user "CMCCAdmin"
set pwd "aDm8H%MdA"

spawn telnet $host
expect "Login: "
send "$user\n"
sleep 0.1
expect "Password: "
send "$pwd\n"
sleep 0.1
expect "~ $ "
send "su\n"
sleep 0.1
expect "Password: "
send "$pwd\n"
sleep 0.1
interact

运行该脚本后即可登录光猫并获取root权限。

1
2
3
4
5
6
7
8
9
10
11
 ~ ~/scripts/telnet_modem
spawn telnet 192.168.1.1
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.

Login: CMCCAdmin
Password:
~ $ su
Password:
/ #

4. 配置IPv6防火墙

光猫的IPv6防火墙可通过ip6tables命令直接配置。登录光猫后运行如下命令:

1
2
ip6tables -I FORWARD -p tcp -m multiport --dports 10000:10009,12345 -j ACCEPT
ip6tables -I FORWARD -p udp -m multiport --dports 10000:10009,12345 -j ACCEPT

即可让光猫转发目标端口为10000~10009、12345的tcp/udp流量。

光猫入站防火墙

5. 持久化IPv6防火墙

光猫重启后以上设置的防火墙规则会被清除,其它文章[2]提到的持久化方式笔者没能复现。所以笔者编写了一个Python脚本用于配置防火墙端口,并通过crontab定期执行来实现持久化地效果:

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
#!/usr/bin/env python3
import telnetlib
from datetime import datetime

need_forward = {'10000:10009', '12345'} # 需开放端口
host, timeout = '192.168.1.1', 3
user, pwd = 'CMCCAdmin', 'aDm8H%MdA'

print(str(datetime.now())[:19])
# 登录路由器
tn = telnetlib.Telnet(host, timeout=timeout)
def exec(expect: str, command: str) -> str:
expectBytes = expect.encode('utf-8')
content = tn.read_until(expectBytes, timeout=timeout)
if not content.endswith(expectBytes):
raise ValueError('expect {}, got {}'.format(repr(expect), repr(content.decode('utf-8'))))
tn.write(command.encode('utf-8') + b'\n')
# print(repr(content.decode('utf-8')))
return content.decode('utf-8')
exec('Login: ', user)
exec('Password: ', pwd)
exec('~ $ ', 'su')
exec('Password: ', pwd)

# 查询已开放端口
def forwarded_ports() -> set:
exec('/ # ', 'ip6tables -L FORWARD')
forwarded = set()
for line in exec('/ # ', '').split('\n'):
line = line.strip()
if not line.startswith('ACCEPT'):
continue
forwarded.update(line.split()[-1].split(','))
return forwarded
forwarded = forwarded_ports()
# print('forwarded: ', forwarded)

# 新增未开放端口
new_ports = need_forward - forwarded
if new_ports:
ports_str = ','.join(new_ports)
exec('/ # ', 'ip6tables -I FORWARD -p tcp -m multiport --dports {} -j ACCEPT'.format(ports_str))
exec('/ # ', 'ip6tables -I FORWARD -p udp -m multiport --dports {} -j ACCEPT'.format(ports_str))
forwarded = forwarded_ports()
print('forwarded: ', forwarded)

tn.close()
1
*/1 * * * * /home/worker/scripts/cron/router_ip6tables.py >> ~/ram/router_ip6tables.log 2>&1

6. 后记

网上其它文章[3][4]详细介绍了如何获取光猫宽带拨号/超级管理员账号密码、如何桥接路由器。但对于可以屏蔽光猫IP地址自动分配[5]、配置光猫防火墙的笔者来说,桥接已经没有什么吸引力了。另外笔者发现,即使通过超级管理员登录光猫后台,在网页上配置DMZ/虚拟主机配置等防火墙规则也不会实际生效,实在离谱。

不可否认的是,桥接在绝大多数场景都是一步到位的便捷选择。但对于不方便进行桥接的笔者来说,iptables真香。

引用


H2-2光猫配置IPv6防火墙
https://www.yooo.ltd/2022/12/31/h2-2-modem-ip6tables/
作者
OrangeWolf
发布于
2022年12月31日
许可协议