logo NodeSeekbeta

realm一键转发脚本,支持ipv6转发(12.21更新)

  • @wcwq99 #77 嗯,大佬,只能在脚本停止面板,然后,启动面板,面板里面操作Realm 的重启不行的

  • bd

  • @道法自然 #74
    大佬,在您的单个添加基础上,实现了批量添加,请您核实,如果可能,麻烦您更新github,
    realm/web/templates/index.html

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Realm 转发管理面板</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                margin: 0;
                padding: 20px;
                background-color: #f4f4f4;
            }
            h1 {
                color: #333;
                text-align: center;
            }
            .container {
                max-width: 800px;
                margin: 0 auto;
                background-color: #fff;
                padding: 20px;
                border-radius: 5px;
                box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            }
            button {
                padding: 10px 15px;
                margin: 5px;
                border: none;
                border-radius: 5px;
                background-color: #28a745;
                color: white;
                cursor: pointer;
                transition: background-color 0.3s;
            }
            button:hover {
                background-color: #218838;
            }
            table {
                width: 100%;
                border-collapse: collapse;
                margin-top: 20px;
            }
            th, td {
                border: 1px solid #ddd;
                padding: 10px;
                text-align: left;
            }
            th {
                background-color: #f2f2f2;
            }
            .form-group {
                margin-bottom: 15px;
            }
            .form-group label {
                display: block;
                margin-bottom: 5px;
            }
            .form-group input {
                width: calc(100% - 22px);
                padding: 10px;
                border: 1px solid #ccc;
                border-radius: 5px;
            }
            #output {
                margin-top: 20px;
                background-color: #fff;
                padding: 10px;
                border: 1px solid #ccc;
                border-radius: 5px;
                min-height: 50px;
                white-space: pre-wrap; /* 保持空格和换行 */
            }
            .status-tag {
                display: inline-flex;
                align-items: center;
                padding: 4px 8px;
                font-size: 14px;
                line-height: 20px;
                border-radius: 4px;
                margin-left: 10px;
                font-weight: 500;
            }
    
            .status-tag.running {
                background-color: #52c41a;
                color: white;
            }
    
            .status-tag.stopped {
                background-color: #ff4d4f;
                color: white;
            }
    
            .status-wrapper {
                display: inline-flex;
                align-items: center;
                margin-left: 15px;
            }
    
            .status-label {
                color: #666;
                margin-right: 8px;
            }
    
            .button-group {
                display: flex;
                align-items: center;
                margin-bottom: 20px;
            }
        </style>
    </head>
    <body>
    
    <div class="container">
        <h1>Realm 转发管理面板</h1>
    
        <div class="button-group">
            <button id="startButton">启动服务</button>
            <button id="stopButton">停止服务</button>
            <button id="logoutButton">登出</button>
            <div class="status-wrapper">
                <span class="status-label">状态:</span>
                <span id="serviceStatus" class="status-tag">检查中...</span>
            </div>
        </div>
    
        <div id="output"></div>
    
        <h2>当前转发规则</h2>
        <table id="forwardingTable">
            <thead>
                <tr>
                    <th>序号</th>
                    <th>中转端口</th>
                    <th>落地鸡 IP</th>
                    <th>目标端口</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <!-- 动态填充转发规则 -->
            </tbody>
        </table>
    
        <h2>添加转发规则</h2>
        <div class="form-group">
            <label for="localPort">中转端口:</label>
            <input type="number" id="localPort" required>
        </div>
        <div class="form-group">
            <label for="remoteIP">落地鸡 IP:</label>
            <input type="text" id="remoteIP" required>
        </div>
        <div class="form-group">
            <label for="remotePort">目标端口:</label>
            <input type="number" id="remotePort" required>
        </div>
        <button id="addRuleButton">添加规则</button>
    
        <h2>批量添加转发规则</h2>
        <div class="form-group">
            <label for="batchInput">批量添加规则 (格式:localPort:remoteIP:remotePort,每条规则一行):</label>
            <textarea id="batchInput" rows="5" style="width: 100%;"></textarea>
        </div>
        <button id="addBatchButton">批量添加规则</button>
    
    </div>
    
    <script>
        async function updateServiceStatus() {
            try {
                const response = await fetch(`/check_status`, {
                    method: 'GET'
                });
                
                if (!response.ok) {
                    throw new Error('检查状态失败:' + response.statusText);
                }
    
                const data = await response.json();
                const statusElement = document.getElementById('serviceStatus');
                
                if (data.status === "启用") {
                    statusElement.textContent = "运行中";
                    statusElement.className = 'status-tag running';
                } else {
                    statusElement.textContent = "已停止";
                    statusElement.className = 'status-tag stopped';
                }
            } catch (error) {
                console.error('更新状态失败:', error);
                document.getElementById('serviceStatus').textContent = '未知';
                document.getElementById('serviceStatus').className = 'status-tag stopped';
            }
        }
    
        // 启动服务
        document.getElementById('startButton').onclick = async function() {
            try {
                const response = await fetch(`/start_service`, {
                    method: 'POST'
                });
                
                if (!response.ok) {
                    throw new Error('启动服务失败:' + response.statusText);
                }
    
                const data = await response.json();
                document.getElementById('output').innerText = data.message || '服务启动成功';
                await updateServiceStatus();
            } catch (error) {
                console.error('启动服务失败:', error);
                document.getElementById('output').innerText = error.message;
            }
        };
    
        // 停止服务
        document.getElementById('stopButton').onclick = async function() {
            try {
                const response = await fetch(`/stop_service`, {
                    method: 'POST'
                });
                
                if (!response.ok) {
                    throw new Error('停止服务失败:' + response.statusText);
                }
    
                const data = await response.json();
                document.getElementById('output').innerText = data.message || '服务停止成功';
                await updateServiceStatus();
            } catch (error) {
                console.error('停止服务失败:', error);
                document.getElementById('output').innerText = error.message;
            }
        };
    
        // 添加转发规则
        document.getElementById('addRuleButton').onclick = async function() {
            const localPort = document.getElementById('localPort').value;
            const remoteIP = document.getElementById('remoteIP').value;
            const remotePort = document.getElementById('remotePort').value;
    
            try {
                const response = await fetch(`/add_rule`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        listen: `0.0.0.0:${localPort}`,
                        remote: `${remoteIP}:${remotePort}`
                    }),
                });
    
                if (!response.ok) {
                    throw new Error('添加规则失败:' + response.statusText);
                }
    
                alert('转发规则添加成功!');
                await fetchForwardingRules(); // 刷新规则列表
            } catch (error) {
                console.error('添加规则失败:', error);
                alert('添加规则失败:' + error.message);
            }
        };
    
        // 批量添加转发规则
        document.getElementById('addBatchButton').onclick = async function() {
            const batchInput = document.getElementById('batchInput').value.trim();
            const rules = batchInput.split('\n').map(line => {
                const [localPort, remoteIP, remotePort] = line.split(':');
                return { listen: `0.0.0.0:${localPort}`, remote: `${remoteIP}:${remotePort}` };
            });
    
            try {
                // 遍历每个规则并逐个添加
                for (const rule of rules) {
                    const response = await fetch(`/add_rule`, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(rule),
                    });
    
                    if (!response.ok) {
                        throw new Error(`批量添加规则失败:${response.statusText}`);
                    }
                }
    
                alert('批量转发规则添加成功!');
                await fetchForwardingRules(); // 刷新规则列表
            } catch (error) {
                console.error('批量添加规则失败:', error);
                alert('批量添加规则失败:' + error.message);
            }
        };
    
        // 删除转发规则
        async function deleteRule(listenAddress) {
            try {
                const response = await fetch(`/delete_rule?listen=${encodeURIComponent(listenAddress)}`, {
                    method: 'DELETE'
                });
    
                if (!response.ok) {
                    throw new Error('删除规则失败:' + response.statusText);
                }
    
                alert('转发规则删除成功!');
                await fetchForwardingRules(); // 刷新规则列表
            } catch (error) {
                console.error('删除规则失败:', error);
                alert('删除规则失败:' + error.message);
            }
        }
    
        // 获取当前转发规则
        async function fetchForwardingRules() {
            try {
                const response = await fetch(`/get_rules`);
                if (!response.ok) {
                    throw new Error('获取规则失败:' + response.statusText);
                }
                const rules = await response.json();
                const tbody = document.querySelector('#forwardingTable tbody');
                tbody.innerHTML = ''; // 清空现有规则
    
                rules.forEach((rule, index) => {
                    const row = document.createElement('tr');
                    let localPort = '', remoteIP = '', remotePort = '';
    
                    // 处理本地端口
                    if (rule.listen) {
                        [, localPort] = rule.listen.split(':');
                    }
    
                    // 处理远程地址和端口
                    if (rule.remote) {
                        if (rule.remote.includes('[')) {
                            const matches = rule.remote.match(/\[(.*)\]:(.*)$/);
                            if (matches) {
                                remoteIP = matches[1];
                                remotePort = matches[2];
                            }
                        } else if (rule.remote.includes(':')) {
                            const colonCount = (rule.remote.match(/:/g) || []).length;
                            if (colonCount > 1) {
                                const lastColon = rule.remote.lastIndexOf(':');
                                remoteIP = rule.remote.substring(0, lastColon);
                                remotePort = rule.remote.substring(lastColon + 1);
                            } else {
                                [remoteIP, remotePort] = rule.remote.split(':');
                            }
                        }
                    }
    
                    row.innerHTML = `
                        <td>${index + 1}</td>
                        <td>${localPort || 'N/A'}</td>
                        <td>${remoteIP || 'N/A'}</td>
                        <td>${remotePort || 'N/A'}</td>
                        <td><button onclick="deleteRule('${rule.listen || ''}')">删除</button></td>
                    `;
                    tbody.appendChild(row);
                });
            } catch (error) {
                console.error('获取转发规则失败:', error);
                alert('获取转发规则失败:' + error.message);
            }
        }
    
        // 页面加载时获取转发规则和服务状态
        window.onload = async function() {
            await fetchForwardingRules();
            await updateServiceStatus();
            
            // 每10秒更新一次状态
            setInterval(updateServiceStatus, 10000);
        };
    
        // 登出功能
        document.getElementById('logoutButton').onclick = async function() {
            try {
                const response = await fetch('/logout', {
                    method: 'POST'
                });
                
                if (!response.ok) {
                    throw new Error('登出失败:' + response.statusText);
                }
    
                window.location.href = '/login';
            } catch (error) {
                console.error('登出失败:', error);
                alert('登出失败:' + error.message);
            }
        };
    </script>
    
    </body>
    </html>
    
    
  • bd

  • 另外贴一份未经严格测试的,重复端口检测,既是如果本地端口已经在规则中,提示端口被占用

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Realm 转发管理面板</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                margin: 0;
                padding: 20px;
                background-color: #f4f4f4;
            }
            h1 {
                color: #333;
                text-align: center;
            }
            .container {
                max-width: 800px;
                margin: 0 auto;
                background-color: #fff;
                padding: 20px;
                border-radius: 5px;
                box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            }
            button {
                padding: 10px 15px;
                margin: 5px;
                border: none;
                border-radius: 5px;
                background-color: #28a745;
                color: white;
                cursor: pointer;
                transition: background-color 0.3s;
            }
            button:hover {
                background-color: #218838;
            }
            table {
                width: 100%;
                border-collapse: collapse;
                margin-top: 20px;
            }
            th, td {
                border: 1px solid #ddd;
                padding: 10px;
                text-align: left;
            }
            th {
                background-color: #f2f2f2;
            }
            .form-group {
                margin-bottom: 15px;
            }
            .form-group label {
                display: block;
                margin-bottom: 5px;
            }
            .form-group input {
                width: calc(100% - 22px);
                padding: 10px;
                border: 1px solid #ccc;
                border-radius: 5px;
            }
            #output {
                margin-top: 20px;
                background-color: #fff;
                padding: 10px;
                border: 1px solid #ccc;
                border-radius: 5px;
                min-height: 50px;
                white-space: pre-wrap; /* 保持空格和换行 */
            }
            .status-tag {
                display: inline-flex;
                align-items: center;
                padding: 4px 8px;
                font-size: 14px;
                line-height: 20px;
                border-radius: 4px;
                margin-left: 10px;
                font-weight: 500;
            }
    
            .status-tag.running {
                background-color: #52c41a;
                color: white;
            }
    
            .status-tag.stopped {
                background-color: #ff4d4f;
                color: white;
            }
    
            .status-wrapper {
                display: inline-flex;
                align-items: center;
                margin-left: 15px;
            }
    
            .status-label {
                color: #666;
                margin-right: 8px;
            }
    
            .button-group {
                display: flex;
                align-items: center;
                margin-bottom: 20px;
            }
        </style>
    </head>
    <body>
    
    <div class="container">
        <h1>Realm 转发管理面板</h1>
    
        <div class="button-group">
            <button id="startButton">启动服务</button>
            <button id="stopButton">停止服务</button>
            <button id="logoutButton">登出</button>
            <div class="status-wrapper">
                <span class="status-label">状态:</span>
                <span id="serviceStatus" class="status-tag">检查中...</span>
            </div>
        </div>
    
        <div id="output"></div>
    
        <h2>当前转发规则</h2>
        <table id="forwardingTable">
            <thead>
                <tr>
                    <th>序号</th>
                    <th>中转端口</th>
                    <th>落地鸡 IP</th>
                    <th>目标端口</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <!-- 动态填充转发规则 -->
            </tbody>
        </table>
    
        <h2>添加转发规则</h2>
        <div class="form-group">
            <label for="localPort">中转端口:</label>
            <input type="number" id="localPort" required>
        </div>
        <div class="form-group">
            <label for="remoteIP">落地鸡 IP:</label>
            <input type="text" id="remoteIP" required>
        </div>
        <div class="form-group">
            <label for="remotePort">目标端口:</label>
            <input type="number" id="remotePort" required>
        </div>
        <button id="addRuleButton">添加规则</button>
    
        <h2>批量添加转发规则</h2>
        <div class="form-group">
            <label for="rulesInput">请输入转发规则(每行一个规则,中转端口:落地鸡 IP:目标端口):</label>
            <textarea id="rulesInput" rows="5" style="width: 100%;"></textarea>
        </div>
        <button id="addBatchRulesButton">批量添加规则</button>
    
    </div>
    
    <script>
        // 获取当前转发规则
        async function fetchForwardingRules() {
            try {
                const response = await fetch(`/get_rules`);
                if (!response.ok) {
                    throw new Error('获取规则失败:' + response.statusText);
                }
                const rules = await response.json();
                const tableBody = document.querySelector('#forwardingTable tbody');
                tableBody.innerHTML = ''; // 清空现有规则
    
                // 创建当前规则的端口占用列表
                const usedPorts = new Set();
                rules.forEach(rule => {
                    const localPort = rule.listen.split(':')[1];
                    usedPorts.add(localPort); // 将已占用的端口加入集合
                });
    
                // 在表格中显示当前规则
                rules.forEach((rule, index) => {
                    const row = document.createElement('tr');
                    row.innerHTML = `
                        <td>${index + 1}</td>
                        <td>${rule.listen.split(':')[1]}</td>
                        <td>${rule.remote.split(':')[0]}</td>
                        <td>${rule.remote.split(':')[1]}</td>
                        <td><button onclick="deleteRule('${rule.listen}')">删除</button></td>
                    `;
                    tableBody.appendChild(row);
                });
    
                // 返回已占用的端口集合
                return usedPorts;
    
            } catch (error) {
                console.error('获取转发规则失败:', error);
                alert('获取转发规则失败:' + error.message);
                return new Set(); // 如果获取规则失败,返回空集合
            }
        }
    
        // 删除转发规则
        async function deleteRule(listenAddress) {
            try {
                const response = await fetch(`/delete_rule?listen=${encodeURIComponent(listenAddress)}`, {
                    method: 'DELETE',
                });
    
                if (response.ok) {
                    alert('规则已删除');
                    await fetchForwardingRules(); // 刷新规则列表
                } else {
                    alert('删除规则失败');
                }
            } catch (error) {
                console.error('删除规则失败:', error);
                alert('删除规则失败:' + error.message);
            }
        }
    
        // 启动服务
        document.getElementById('startButton').onclick = async function() {
            try {
                const response = await fetch(`/start_service`, {
                    method: 'POST'
                });
    
                if (!response.ok) {
                    throw new Error('启动服务失败:' + response.statusText);
                }
    
                const data = await response.json();
                document.getElementById('output').innerText = data.message || '服务启动成功';
                await updateServiceStatus(); // 更新状态
            } catch (error) {
                console.error('启动服务失败:', error);
                document.getElementById('output').innerText = error.message;
            }
        };
    
        // 停止服务
        document.getElementById('stopButton').onclick = async function() {
            try {
                const response = await fetch(`/stop_service`, {
                    method: 'POST'
                });
    
                if (!response.ok) {
                    throw new Error('停止服务失败:' + response.statusText);
                }
    
                const data = await response.json();
                document.getElementById('output').innerText = data.message || '服务停止成功';
                await updateServiceStatus(); // 更新状态
            } catch (error) {
                console.error('停止服务失败:', error);
                document.getElementById('output').innerText = error.message;
            }
        };
    
        // 更新服务状态
        async function updateServiceStatus() {
            try {
                const response = await fetch(`/check_status`, {
                    method: 'GET'
                });
    
                if (!response.ok) {
                    throw new Error('检查状态失败:' + response.statusText);
                }
    
                const data = await response.json();
                const statusElement = document.getElementById('serviceStatus');
    
                if (data.status === "启用") {
                    statusElement.textContent = "运行中";
                    statusElement.className = 'status-tag running';
                } else {
                    statusElement.textContent = "已停止";
                    statusElement.className = 'status-tag stopped';
                }
            } catch (error) {
                console.error('更新状态失败:', error);
                document.getElementById('serviceStatus').textContent = '未知';
                document.getElementById('serviceStatus').className = 'status-tag stopped';
            }
        }
    
        // 单个添加转发规则
        document.getElementById('addRuleButton').onclick = async function() {
            const localPort = document.getElementById('localPort').value;
            const remoteIP = document.getElementById('remoteIP').value;
            const remotePort = document.getElementById('remotePort').value;
    
            try {
                const usedPorts = await fetchForwardingRules(); // 获取已占用的端口
    
                if (usedPorts.has(localPort)) {
                    alert(`端口 ${localPort} 已被占用,请选择另一个端口`);
                    return;
                }
    
                const response = await fetch(`/add_rule`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        listen: `0.0.0.0:${localPort}`,
                        remote: `${remoteIP}:${remotePort}`
                    }),
                });
    
                if (!response.ok) {
                    throw new Error('添加规则失败:' + response.statusText);
                }
    
                alert('转发规则添加成功!');
                await fetchForwardingRules(); // 刷新规则列表
            } catch (error) {
                console.error('添加规则失败:', error);
                alert('添加规则失败:' + error.message);
            }
        };
    
        // 批量添加转发规则
        document.getElementById('addBatchRulesButton').onclick = async function() {
            const rulesInput = document.getElementById('rulesInput').value.trim();
            const rulesList = rulesInput.split('\n').map(line => line.trim()).filter(Boolean);
            const usedPorts = await fetchForwardingRules(); // 获取已占用的端口
    
            let failedRules = [];
            for (const rule of rulesList) {
                const [localPort, remoteIP, remotePort] = rule.split(':');
    
                if (usedPorts.has(localPort)) {
                    failedRules.push(`端口 ${localPort} 已被占用`);
                    continue;
                }
    
                try {
                    const response = await fetch(`/add_rule`, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({
                            listen: `0.0.0.0:${localPort}`,
                            remote: `${remoteIP}:${remotePort}`
                        })
                    });
    
                    if (!response.ok) {
                        throw new Error('添加规则失败:' + response.statusText);
                    }
    
                    usedPorts.add(localPort); // 添加成功后将该端口加入已占用列表
    
                } catch (error) {
                    failedRules.push(`规则 ${rule} 添加失败:${error.message}`);
                }
            }
    
            if (failedRules.length > 0) {
                alert(failedRules.join('\n'));
            } else {
                alert('所有规则已成功添加');
                await fetchForwardingRules(); // 刷新规则列表
            }
        };
    
        // 登出功能
        document.getElementById('logoutButton').onclick = async function() {
            try {
                const response = await fetch('/logout', {
                    method: 'POST'
                });
    
                if (!response.ok) {
                    throw new Error('登出失败:' + response.statusText);
                }
    
                window.location.href = '/login'; // 重定向到登录页面
            } catch (error) {
                console.error('登出失败:', error);
                alert('登出失败:' + error.message);
            }
        };
    
        // 页面加载时获取转发规则和服务状态
        window.onload = async function() {
            await fetchForwardingRules();
            await updateServiceStatus();
    
            // 每10秒更新一次服务状态
            setInterval(updateServiceStatus, 10000);
        };
    </script>
    
    </body>
    </html>
    
    
    
  • 好贴帮顶,收藏

  • @niudapao #72 嗯?有点没理解 是放行服务器端口吗

  • @小兔子 #85 好,感谢老哥,我周末回去测试没问题再更新

  • 膜拜,大佬装完这个可以在面板上自己配置转发吗?

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有71845位seeker

🎉欢迎新用户🎉