NAT1 利用 LUCKY+自动化脚本实现无感化 PLEX 外网访问

7 天前
 fl0w1nd

效果

能在没有公网,仅拥有 NAT1 的情况下,做到无感 PLEX 外网访问

前提

相关链接

Lucky 项目地址 Python-plexapi

配置

脚本配置

pip3 install plexapi

这是需要修改的内容

# Plex 账号信息
PLEX_USERNAME = "example@qq.com"
PLEX_PASSWORD = "password"

PLEX_SERVER_BASEURL = "http://192.168.3.6:32400"  # 替换为你的 Plex 服务器 URL

TOKEN_FILE = "/root/plex_token.json"  # 保存 PLEX Token 的路径

这是脚本代码

import os
import sys
import json
import requests
from plexapi.server import PlexServer

# Plex 账号信息
PLEX_USERNAME = "example@qq.com"
PLEX_PASSWORD = "password"

# Plex API URL
LOGIN_URL = "https://plex.tv/users/sign_in.json"
PLEX_SERVER_BASEURL = "http://192.168.3.6:32400"  # 替换为你的 Plex 服务器 URL

# 登录请求的头信息
HEADERS = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "X-Plex-Client-Identifier": "MyPlexApp"
}

# 获取新令牌的登录请求数据
data = {
    "user": {
        "login": PLEX_USERNAME,
        "password": PLEX_PASSWORD
    }
}

def get_plex_token():
    """
    通过向 Plex API 发送登录请求获取 Plex 认证令牌。
    """
    try:
        response = requests.post(LOGIN_URL, headers=HEADERS, data=json.dumps(data))
        if response.status_code == 201:  # 状态码 201 表示登录成功
            return response.json()['user']['authentication_token']
        else:
            print(f"获取令牌失败。状态码: {response.status_code}")
            return None
    except Exception as e:
        print(f"认证过程中发生错误: {str(e)}")
        return None

def read_token_from_file(token_file):
    """
    从指定的 JSON 文件中读取 Plex 令牌。
    """
    if os.path.exists(token_file):
        try:
            with open(token_file, 'r') as file:
                data = json.load(file)
                return data.get('token')
        except Exception as e:
            print(f"读取令牌文件时发生错误: {str(e)}")
            return None
    else:
        return None

def save_token_to_file(token_file, token):
    """
    将 Plex 令牌保存到指定的 JSON 文件中。
    """
    try:
        with open(token_file, 'w') as file:
            json.dump({"token": token}, file)
    except Exception as e:
        print(f"保存令牌到文件时发生错误: {str(e)}")

def check_token_validity(baseurl, token):
    """
    通过向服务器发送验证请求来检查 Plex 令牌的有效性。
    """
    try:
        check_url = f"{baseurl}/library/sections?X-Plex-Token={token}"
        response = requests.get(check_url)
        return response.status_code == 200
    except Exception as e:
        print(f"检查令牌有效性时发生错误: {str(e)}")
        return False

def modify_port(plex, new_port):
    """
    修改 Plex 服务器设置中的手动端口映射。
    """
    manual_port_setting = plex.settings.get('manualPortMappingPort')
    
    if manual_port_setting:
        try:
            manual_port_setting.set(new_port)
            plex.settings.save()
            print(f"手动端口映射已成功更改为: {new_port}")
        except Exception as e:
            print(f"修改端口或保存设置时发生错误: {str(e)}")
    else:
        print("无法找到手动端口映射设置。")

if __name__ == "__main__":
    # 第一步:解析命令行参数,获取新的端口号
    if len(sys.argv) < 2:
        print("用法: python3 modify.py <new_port>")
        sys.exit(1)

    try:
        NEW_PORT = int(sys.argv[1])  # 将提供的端口号转换为整数
    except ValueError:
        print("无效的端口号。请提供有效的整数。")
        sys.exit(1)

    # 第二步:定义令牌存储文件
    TOKEN_FILE = "/root/plex_token.json"  # Token 路径

    # 第三步:从文件中读取令牌或生成新令牌
    PLEX_TOKEN = read_token_from_file(TOKEN_FILE)

    # 第四步:如果文件中没有令牌,或者令牌无效,则生成新令牌
    if PLEX_TOKEN is None or not check_token_validity(PLEX_SERVER_BASEURL, PLEX_TOKEN):
        PLEX_TOKEN = get_plex_token()
        if PLEX_TOKEN:
            save_token_to_file(TOKEN_FILE, PLEX_TOKEN)
        else:
            print("获取有效令牌失败。")
            sys.exit(1)

    # 第五步:使用 plexapi 连接到 Plex 服务器并修改手动端口
    try:
        plex = PlexServer(PLEX_SERVER_BASEURL, PLEX_TOKEN)
        print("成功连接到 Plex 服务器!")
        
        # 修改手动端口映射(使用传入的端口号)
        modify_port(plex, NEW_PORT)
    except Exception as e:
        print(f"连接 Plex 服务器或修改设置时发生错误: {str(e)}")

Lucky 配置

创建一个 TCP 穿透规则,这里我指定了一个空闲端口为 13333 ,并且不使用 LUCKY 的内置端口转发。开启自定义脚本触发,代码如下:

python3 /root/modify_port.py ${port}

if [ $? -ne 0 ]; then
    echo "Python script execution failed with exit code $?."
fi

注意此处代码的 /root/modify_port.py 就是刚刚的 python 执行脚本的实际路径。

随后确认即可,规则创建关闭后稍时即可打洞成功。

端口转发

由于我们刚刚指定了端口,并且没有使用 Lucky 内置的端口转发,因此我们需要用防火墙配置手动端口转发

如果你是主路由,源区域应该是防火墙的“WAN”区域,我是旁路由,所以源区域为 LAN

外部端口就是刚刚打洞绑定的端口,例如我刚刚在 LUCKY 配置了 13333 端口

目前区域即可 LAN ,内部 IP 地址即为 PLEX 所在主机 IP ,内部端口通常为 PLEX Server 默认端口 32400

常见问题

解决方案有下列几种:

  1. 通过 Openclash 的仅允许常用端口流量功能,可以让打洞的流量不经过 Openclash ,即不包含 3478 端口流量
  2. 通过 Openclash 的黑白名单功能中的绕过核心的来源端口功能

设置几个打洞时绑定的预设端口,这些端口流量就不会经过 Openclash 了,但配置中也指出了,Fake ip 模式下只能过滤纯 IP 类型请求。

其它请自行发挥,包括但不限于使用 Openclash 的开发者选项,或者修改防火墙来实现

722 次点击
所在节点    宽带症候群
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1084355

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX