操作场景
家庭宽带的公网 IP 是由运营商分配的,运营商可能会不定时更换这些 IP 地址。如果您使用家庭宽带远程登录云服务器,并且安全组设置为只允许特定的公网 IP 登录,那么每当 IP 地址被更换时,您都需要对应地更新安全组规则中的 IP 地址,以便正常登录云服务器。部分办公网络也面临同样的问题。
本文将指导您在本地终端中通过调用接口自动获取本地出口的公网 IP,并将其更新到安全组规则里,减轻运营商更换公网 IP 所带来的影响。
前提条件
完成 TCCLI 工具安装,安装方式参考 安装TCCLI。
完成 TCCLI 工具配置,配置方式参考 配置TCCLI,通过浏览器登录腾讯云账号并授权以获取凭证。
方案说明
基本原理
CreateSecurityGroupPolicies 接口的 SecurityGroupPolicySet 中源地址(SourceCidr)支持传入字符串 MY_PUBLIC_IP,表示当前访问 API 的公网 IP 地址。您可通过 TCCLI 工具快速将本地公网出口 IP 添加到安全组规则中,创建放通对应 IP 的安全组规则,并添加备注,以便以后根据备注识别和删除旧的安全组规则。
主要操作指令如下:
1. 指定安全组所在地域,地域列表可通过接口 DescribeRegions 获取。
tccli configure set region ap-guangzhou # ap-guangzhou 表示安全组所在地域,可按实际情况替换
2. 添加安全组规则,并添加备注以便后面识别和删除。
tccli vpc CreateSecurityGroupPolicies --SecurityGroupId sg-mdw2qvp3 --SecurityGroupPolicySet '{"Ingress":[{"Protocol":"tcp","Port":"22","CidrBlock":"MY_PUBLIC_IP","Action":"ACCEPT","PolicyIndex":"0","PolicyDescription":""}]}'# 录入信息说明:# sg-mdw2qvp3 表示需要修改的安全组ID# Ingress表示入添加入站规则# tcp表示协议类型# Port表示远程登录需要放通端口,常见端口包括22,3389等# CidrBlock表示需要放通的源地址,此处输入MY_PUBLIC_IP,表示当前访问云API的通往IP# Action访问动过选择ACCEPT表示允许访问# PolicyIndex输入0,表示将该规则添加到安全组第一条# PolicyDescription表示备注信息,用户可根据实际情况自行填入。若不输入,则通过"MY_PUBLIC_IP"入参创建的安全组,默认备注内容为“Replaced-From-MY_PUBLIC_IP”
3. 查询自动创建的安全组规则,并删除旧的规则。
tccli vpc DescribeSecurityGroupPolicies --SecurityGroupId sg-mdw2qvp3 --Filters '[{"Name":"description","Values":["Replaced-From-MY_PUBLIC_IP"]}]'# sg-mdw2qvp3 表示需要修改的安全组ID,通过Filters字段,填入备注中的"Replaced-From-MY_PUBLIC_IP",快速查看规则添加情况,获取到安全组规则的PolicyIndex值tccli vpc DeleteSecurityGroupPolicies --SecurityGroupId sg-mdw2qvp3 --SecurityGroupPolicySet '{"Ingress":[{"PolicyIndex":"N"}]}'# sg-mdw2qvp3 表示要修改的安全组ID。PolicyIndex值"N"要替换成要删除的安全组规则的实际PolicyIndex值,如"PolicyIndex":"2"
注意:
安全组规则变更会影响服务器访问情况,配置前请仔细核对信息是否准确,避免影响业务正常运行。
操作步骤


信息确认

创建本地脚本
创建脚本文件
vi CreateSecurityGroupPolicies.py # CreateSecurityGroupPolicies.py表示脚本名称
说明:
示例脚本
说明:
1. 我们提供示例脚本供您参考,绝大部分使用场景可直接使用。
2. 考虑到使用场景多样和公网环境复杂,我们针对典型的特殊场景提供了对应的参数供您调整。
当同时有多个潜在登录终端时,会出现多个终端先后使用本脚本修改同一个安全组的情况。为避免最后执行此脚本的终端修改了安全组对其他终端的放通规则,本脚本支持通过 HOSTNAME 参数区分不同终端,不同终端的规则互不影响。该参数默认为
Auto-Created-For-Hostname-$主机名。当单个公网宽带出口同时有多个相互切换的 IP 时,本脚本支持通过 MAX_RESERVED_NUM 调整安全组对单终端放通的 IP 数量上限,即保留最近 MAX_RESERVED_NUM 次放通的 IP。脚本默认单终端所在的宽带出口只有1个公网 IP,即 MAX_RESERVED_NUM = 1。
#!/usr/bin/env python# -*- coding: utf-8 -*-import jsonimport optparseimport socketimport subprocessimport sys# 默认配置,可直接在此处修改,也可通过传参来调整HOSTNAME = socket.gethostname() # 主机名,用于区分不同客户端的放通策略MAX_RESERVED_NUM = 1 # 自动放通策略的最大保留数量,用于清理过期的策略,存在多个出口IP时,可以按需调整POLICY_PROTOCOL = 'TCP' # 要放通的协议,通常是: TCPPOLICY_PORT = '22' # 要放通的端口,通常是: 22(Linux/Unix)、3389(Windows)def get_policy_description():return 'Auto-Created-For-Hostname-%s' % HOSTNAMEdef get_describe_filters():return [{'Name': 'direction','Values': ['INBOUND']}, {'Name': 'poly','Values': ['ACCEPT']}, {'Name': 'protocol-type','Values': [POLICY_PROTOCOL]}, {'Name': 'port','Values': [POLICY_PORT]}, {'Name': 'description','Values': [get_policy_description()]}]def get_create_policy():return {'Ingress': [{'PolicyIndex': 0,'Action': 'ACCEPT','Protocol': POLICY_PROTOCOL,'Port': POLICY_PORT,'CidrBlock': 'MY_PUBLIC_IP', # MY_PUBLIC_IP 会自动替换为本地公网IP'PolicyDescription': get_policy_description(),}]}def get_delete_filters(policies):_registry = {}delete_index_list = []for item in policies:if len(_registry) < MAX_RESERVED_NUM \\and item['CidrBlock'] not in _registry:_registry[item['CidrBlock']] = Noneelse:delete_index_list.append(item['PolicyIndex'])delete_filters = {'Ingress': []}for index in delete_index_list:delete_filters['Ingress'].append({'PolicyIndex': index,'Action': 'ACCEPT','Protocol': POLICY_PROTOCOL,'Port': POLICY_PORT,'PolicyDescription': get_policy_description(),})return delete_filtersdef tccli_cmd(cmd):p = subprocess.Popen('tccli %s' % cmd, shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)std_out, std_err = p.communicate()if p.returncode:sys.stderr.write(std_err.decode('utf-8'))sys.exit(p.returncode)if std_out:return json.loads(std_out.decode('utf-8'))def main(SecurityGroupId):# 添加放通本地公网IP的规则tccli_cmd('vpc CreateSecurityGroupPolicies ''--SecurityGroupId %r ''--SecurityGroupPolicySet %r '% (SecurityGroupId, json.dumps(get_create_policy())))# 查询匹配特定条件的规则r = tccli_cmd('vpc DescribeSecurityGroupPolicies ''--SecurityGroupId %r ''--Filters %r ''--filter "SecurityGroupPolicySet.Ingress" ''--output json'% (SecurityGroupId, json.dumps(get_describe_filters())))# 删除最大保留量以外的规则delete_filters = get_delete_filters(r)if delete_filters['Ingress']:tccli_cmd('vpc DeleteSecurityGroupPolicies ''--SecurityGroupId %r ''--SecurityGroupPolicySet %r '% (SecurityGroupId, json.dumps(delete_filters)))print('done.')if __name__ == '__main__':usage = 'usage: %prog [options] SecurityGroupId [SecurityGroupId ...]'parser = optparse.OptionParser(usage=usage)parser.add_option('-r', '--region')parser.add_option('-n', '--max-reserved-num', type=int,help='default %r' % MAX_RESERVED_NUM)parser.add_option('-N', '--hostname', help='default %r' % HOSTNAME)parser.add_option('-p', '--port', help='default %r' % POLICY_PORT)parser.add_option('-P', '--protocol', help='default %r' % POLICY_PROTOCOL)options, args = parser.parse_args()if options.hostname is not None:HOSTNAME = options.hostnameif options.max_reserved_num is not None:MAX_RESERVED_NUM = options.max_reserved_numif options.port is not None:POLICY_PORT = options.portif options.protocol is not None:POLICY_PROTOCOL = options.protocol# 设置 TCCLI 工作地域if options.region:tccli_cmd('configure set region %s' % options.region)for SecurityGroupId in set(args):main(SecurityGroupId)
运行示例脚本
情况一:直接使用,覆盖大部分场景。
python CreateSecurityGroupPolicies.py -r ap-guangzhou sg-xxxx -p 22# ap-guangzhou表示安全组所在地域,sg-xxxx表示安全组ID,22表示需要放通的端口
情况二:针对典型的特殊场景,您可以根据实例脚本说明调整对应的参数。
python CreateSecurityGroupPolicies.py -N MY_MAC -n 15 -r ap-guangzhou sg-xxxx -p 22# MY_MAC表示HOSTNAME名字,15表示MAX_RESERVED_NUM数量,ap-guangzhou表示安全组所在地域,sg-xxxx表示安全组ID,22表示需要放通的端口
将脚本设置为开机运行或定时运行
说明:
脚本设置为开机运行或定时运行,您可以根据运营商更换公网 IP 的频率,合理设置时间间隔,以便正常登录云服务器。
将脚本设置为开机运行
通过 crontab 工具设置开机运行
1. 打开终端,并执行命令 crontab -e。
crontab -e
2. 编辑定时任务文件,设置开机运行。
@reboot /path/to/Python /path/to/your/CreateSecurityGroupPolicies.py -r ap-guangzhou sg-xxxx# 设置开机运行,ap-guangzhou表示安全组所在地域,sg-xxxx表示安全组ID
3. 保存并关闭文件。
:wq
通过 windows 任务计划程序设置开机运行
1. 打开任务计划程序。

2. 添加计划任务,选择创建任务。

2.1 填写计划任务信息以及选择运行账户。

2.2 “程序或脚本”选择需要运行的脚本,“添加参数(可选)”填写脚本参数。

2.3 配置触发器,选择启动时运行。

3.单击确定保存。
将脚本设置为定时运行
通过crontab工具设置定时运行
1. 打开终端,并执行命令 crontab -e。
crontab -e
2. 编辑定时任务文件,每行表示一个定时任务,可根据需要设置合理的运行时间。
0 0 * * * /path/to/Python /path/to/CreateSecurityGroupPolicies.py -r ap-guangzhou sg-xxxx#表示每天的0点执行脚本。ap-guangzhou表示安全组所在地域,sg-xxxx表示安全组ID
3. 保存。
:wq
通过 windows 任务计划程序设置定时运行
1. 打开任务计划程序。

2. 添加计划任务,选择创建任务。

2.1 填写计划任务信息以及选择运行账户。

2.2 “程序或脚本”选择需要运行的脚本,“添加参数(可选)”填写脚本参数。

2.3 设置定时运行。

3. 确认保存。