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功能。
在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 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防火墙
光猫重启后以上设置的防火墙规则会被清除,其它文章提到的持久化方式笔者没能复现。所以笔者编写了一个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
| 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') 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()
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. 后记
网上其它文章详细介绍了如何获取光猫宽带拨号/超级管理员账号密码、如何桥接路由器。但对于可以屏蔽光猫IP地址自动分配、配置光猫防火墙的笔者来说,桥接已经没有什么吸引力了。另外笔者发现,即使通过超级管理员登录光猫后台,在网页上配置DMZ/虚拟主机配置等防火墙规则也不会实际生效,实在离谱。
不可否认的是,桥接在绝大多数场景都是一步到位的便捷选择。但对于不方便进行桥接的笔者来说,iptables
真香。
引用