魔方云没有自带批量更换ip的功能,甚至没有更换ip的功能。
但是我们能看到v10对接魔方云后,v10后台有更换ip按钮,也就是魔方云有这个更换ip功能只是不让我们用,在魔方云后台要删了ip再添加上完成更换,太麻烦。
既然v10有这个功能,说名功能是存在的,因此同行做了个批量更换ip的python脚本
感谢极点云的贡献!
脚本是在我们电脑上执行的,不是主控服务器,相当于操控我们电脑,帮我们执行多次更换ip的请求。
1、安装python3.6或以上版本
脚本要求我们电脑具备python3.6或以上版本。我们这里推荐3.10.11.访问python搜索安装即可
https://www.python.org/downloads/windows/

我们电脑上双击安装,装好了 有个是否允许加长路径啥的,要允许。
2、电脑执行函数的安装
2.1 在脚本所在文件夹,右键打开终端
2.2 只需要安装requests库,使用pip安装:
pip install requests
这里很多人装不上报错,因为与win11的自带python冲突,那就执行这个
python
py -m pip install requests
2.3 执行脚本
假设你的脚本文件叫 mf_ip_change.py(或者别的名字),放在 C:\Users\666\Downloads 目录下:
python
py mf_ip_change.py
然后根据提示输入魔方云后台地址、要更换的ip的段(比如28.25.21,最后一位不写就是段)token、cookie
接着脚本会搜索,并且问你是否更换。

注意 :这个ip更换原理是:在可用ip里取第一个ip,先增加给云机,再从云机删除老的ip,速度还是很快的。因此再大面积更换ip段之前,需要先禁用老的ip,或者叫老的ip再魔方云里设置的可用节点里移除这台需要换ip的宿主机的可用。
3、token、cookie的获取方法
打开并登陆魔方云后台,然后按f12,勾选保留日志,然后刷新下页面,找到如下文件特征
其实很多文件都包含token\cookie的,随便点点看,有的话 就可以复制了,都是一样的,这个cookie也不是一直不变的,魔方云每次登录都是不一样的,但只要没有让你重新登陆,就都是有效的

python的代码如下,可以创建个txt文件,复制进去保存,修改名字为.py结尾的就行了
python
import requests
import json
import sys
import time
class ServerIPManager:
def __init__(self):
self.session = requests.Session()
self.headers = {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
def set_auth(self, access_token, cookie):
"""设置认证信息"""
self.headers["access-token"] = access_token
self.headers["Cookie"] = cookie
def get_server_ids(self, domain, search_content=""):
"""
获取服务器ID列表
"""
print("=== 步骤1: 获取服务器ID列表 ===")
# 构建请求URL
base_url = f"{domain}/v1/clouds"
params = {
"page": 1,
"per_page": 300,
"sort": "desc",
"orderby": "id",
"searchtype": 0
}
# 如果有搜索内容,添加到参数中
if search_content:
params["search"] = search_content
try:
print(f"正在发送请求到: {base_url}")
# 发送GET请求
response = self.session.get(
base_url,
params=params,
headers=self.headers,
timeout=30
)
# 检查响应状态
if response.status_code == 200:
data = response.json()
# 检查响应数据结构
if "data" in data and isinstance(data["data"], list):
servers = []
# 遍历服务器数据,提取主ID和基本信息
for server in data["data"]:
if "id" in server:
server_info = {
"id": server["id"],
"hostname": server.get("hostname", "未知"),
"mainip": server.get("mainip", "未知"),
"status": server.get("status", "未知")
}
servers.append(server_info)
print(f"找到服务器: ID={server_info['id']}, 主机名={server_info['hostname']}, IP={server_info['mainip']}, 状态={server_info['status']}")
if servers:
print(f"\n=== 获取完成 ===")
print(f"共找到 {len(servers)} 台服务器")
return servers
else:
print("未找到任何服务器数据")
return []
else:
print("响应数据格式不正确,未找到 'data' 字段")
return []
else:
print(f"请求失败,状态码: {response.status_code}")
print("响应内容:", response.text)
return []
except Exception as e:
print(f"获取服务器ID列表时发生错误: {e}")
return []
def get_server_details(self, domain, server_id):
"""
获取服务器详细信息,提取node_id、bwid和原有IP的ID
"""
print(f"\n=== 获取服务器 {server_id} 的详细信息 ===")
url = f"{domain}/v1/clouds/{server_id}"
try:
response = self.session.get(url, headers=self.headers, timeout=30)
if response.status_code == 200:
data = response.json()
# 提取node_id
node_id = data.get("node_id")
if not node_id:
print(f"错误:未找到服务器 {server_id} 的node_id")
return None
# 提取bwid
bwid = None
if "network" in data and len(data["network"]) > 0:
network = data["network"][0]
bwid = network.get("bwid")
if not bwid:
print(f"错误:未找到服务器 {server_id} 的bwid")
return None
# 提取原有IP的ID(主IP的ID)
old_ip_id = None
main_ip = data.get("mainip")
# 从多个位置查找主IP的ID
if "ip" in data and isinstance(data["ip"], list):
for ip_info in data["ip"]:
if ip_info.get("ipaddress") == main_ip:
old_ip_id = ip_info.get("id")
break
if not old_ip_id and "network" in data and len(data["network"]) > 0:
network = data["network"][0]
if "ipaddress" in network and isinstance(network["ipaddress"], list):
for ip_info in network["ipaddress"]:
if ip_info.get("ipaddress") == main_ip:
old_ip_id = ip_info.get("id")
break
if not old_ip_id:
print(f"警告:未找到服务器 {server_id} 主IP {main_ip} 对应的ID")
# 尝试获取第一个IP的ID作为备用
if "ip" in data and len(data["ip"]) > 0:
old_ip_id = data["ip"][0].get("id")
print(f"使用第一个找到的IP ID: {old_ip_id}")
server_details = {
"node_id": node_id,
"bwid": bwid,
"old_ip_id": old_ip_id,
"main_ip": main_ip
}
print(f"服务器 {server_id} 详细信息:")
print(f" - 节点ID: {node_id}")
print(f" - 带宽组ID: {bwid}")
print(f" - 原IP ID: {old_ip_id}")
print(f" - 主IP: {main_ip}")
return server_details
else:
print(f"获取服务器 {server_id} 详情失败,状态码: {response.status_code}")
return None
except Exception as e:
print(f"获取服务器 {server_id} 详情时发生错误: {e}")
return None
def get_free_ips(self, domain, node_id):
"""
获取空闲IP列表
"""
print(f"\n=== 获取节点 {node_id} 的空闲IP ===")
url = f"{domain}/v1/ip/free"
params = {
"node": node_id
}
try:
response = self.session.get(url, params=params, headers=self.headers, timeout=30)
if response.status_code == 200:
data = response.json()
free_ips = []
# 解析空闲IP数据
for ip_group in data:
if "ip" in ip_group and isinstance(ip_group["ip"], list):
for ip_info in ip_group["ip"]:
free_ip = {
"id": ip_info.get("id"),
"ip": ip_info.get("ip"),
"ip_name": ip_group.get("ip_name", "未知")
}
free_ips.append(free_ip)
if free_ips:
print(f"找到 {len(free_ips)} 个空闲IP:")
for ip in free_ips:
print(f" - IP ID: {ip['id']}, IP地址: {ip['ip']}, IP段: {ip['ip_name']}")
return free_ips
else:
print("未找到空闲IP")
return []
else:
print(f"获取空闲IP失败,状态码: {response.status_code}")
return []
except Exception as e:
print(f"获取空闲IP时发生错误: {e}")
return []
def add_new_ip(self, domain, server_id, new_ip_id, bwid):
"""
添加新IP到服务器
"""
print(f"\n=== 为服务器 {server_id} 添加新IP {new_ip_id} ===")
url = f"{domain}/v1/clouds/{server_id}/floatip"
payload = {
"id": server_id,
"ip": [new_ip_id],
"in_bw": None,
"out_bw": None,
"bw_group": bwid,
"ip_type": "normal"
}
try:
response = self.session.post(url, json=payload, headers=self.headers, timeout=30)
if response.status_code == 200:
print(f"成功添加新IP {new_ip_id} 到服务器 {server_id}")
return True
else:
print(f"添加新IP失败,状态码: {response.status_code}")
print("响应内容:", response.text)
return False
except Exception as e:
print(f"添加新IP时发生错误: {e}")
return False
def remove_old_ip(self, domain, server_id, old_ip_id):
"""
删除服务器的旧IP
"""
print(f"\n=== 从服务器 {server_id} 删除旧IP {old_ip_id} ===")
url = f"{domain}/v1/clouds/{server_id}/floatip"
payload = {
"id": server_id,
"ip": [old_ip_id]
}
try:
response = self.session.delete(url, json=payload, headers=self.headers, timeout=30)
if response.status_code == 200:
print(f"成功从服务器 {server_id} 删除旧IP {old_ip_id}")
return True
else:
print(f"删除旧IP失败,状态码: {response.status_code}")
print("响应内容:", response.text)
return False
except Exception as e:
print(f"删除旧IP时发生错误: {e}")
return False
def change_server_ip(self, domain, server_info):
"""
为单个服务器更换IP
"""
server_id = server_info["id"]
print(f"\n{'='*50}")
print(f"开始处理服务器 {server_id} ({server_info['hostname']})")
print(f"{'='*50}")
# 1. 获取服务器详细信息
server_details = self.get_server_details(domain, server_id)
if not server_details:
print(f"跳过服务器 {server_id},无法获取详细信息")
return False
# 2. 获取空闲IP
free_ips = self.get_free_ips(domain, server_details["node_id"])
if not free_ips:
print(f"跳过服务器 {server_id},没有可用的空闲IP")
return False
# 选择第一个空闲IP
new_ip_info = free_ips[0]
new_ip_id = new_ip_info["id"]
new_ip_address = new_ip_info["ip"]
print(f"选择新IP: {new_ip_address} (ID: {new_ip_id})")
# 3. 添加新IP
if not self.add_new_ip(domain, server_id, new_ip_id, server_details["bwid"]):
print(f"服务器 {server_id} 添加新IP失败")
return False
# 等待一段时间让新IP生效
print("等待5秒让新IP生效...")
time.sleep(5)
# 4. 删除旧IP
if server_details["old_ip_id"]:
if not self.remove_old_ip(domain, server_id, server_details["old_ip_id"]):
print(f"服务器 {server_id} 删除旧IP失败")
# 即使删除失败,新IP已经添加,可以认为是部分成功
return True
else:
print(f"服务器 {server_id} 没有找到旧IP ID,跳过删除步骤")
print(f"服务器 {server_id} IP更换完成: {server_details['main_ip']} -> {new_ip_address}")
return True
def batch_change_ips(self, domain, servers):
"""
批量更换服务器IP
"""
print(f"\n{'='*60}")
print(f"开始批量更换IP,共 {len(servers)} 台服务器")
print(f"{'='*60}")
success_count = 0
failed_count = 0
for i, server_info in enumerate(servers, 1):
print(f"\n处理进度: {i}/{len(servers)}")
if self.change_server_ip(domain, server_info):
success_count += 1
else:
failed_count += 1
# 在处理多个服务器之间添加延迟,避免请求过于频繁
if i < len(servers):
print("等待3秒后处理下一台服务器...")
time.sleep(3)
print(f"\n{'='*60}")
print(f"批量更换IP完成")
print(f"成功: {success_count} 台")
print(f"失败: {failed_count} 台")
print(f"{'='*60}")
def pause1(self):
print("程序执行完毕,按 Enter 键继续...")
input()
def main():
"""
主函数
"""
manager = ServerIPManager()
print("=== 魔方云批量更换服务器IP工具 ===")
# 获取用户输入
domain = input("请输入后台域名与路径(例如:https://example.com/baidu): ").strip()
if not domain:
print("错误:域名不能为空")
return
search_content = input("请输入搜索内容(按回车跳过): ").strip()
access_token = input("请输入浏览器F12的access-token: ").strip()
if not access_token:
print("错误:access-token不能为空")
return
cookie = input("请输入请输入浏览器F12的Cookie: (PHPSESSID=一行)").strip()
if not cookie:
print("错误:Cookie不能为空")
return
# 设置认证信息
manager.set_auth(access_token, cookie)
# 获取服务器列表
servers = manager.get_server_ids(domain, search_content)
if not servers:
print("没有找到服务器,程序退出")
return
# 显示服务器列表并确认
print(f"\n找到以下 {len(servers)} 台服务器:")
for server in servers:
print(f" - ID: {server['id']}, 主机名: {server['hostname']}, IP: {server['mainip']}")
confirm = input("\n是否继续批量更换IP?(y/n): ").strip().lower()
if confirm not in ['y', 'yes']:
print("操作已取消")
return
# 开始批量更换IP
manager.batch_change_ips(domain, servers)
manager.pause1()
if __name__ == "__main__":
main()
