<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[流动的风]]></title><description><![CDATA[Code & Tech]]></description><link>https://blog.zcsouls.com</link><image><url>https://blog.zcsouls.com/api/v2/objects/icon/i2widtznkx4w6popqu.png</url><title>流动的风</title><link>https://blog.zcsouls.com</link></image><generator>Shiro (https://github.com/Innei/Shiro)</generator><lastBuildDate>Sat, 18 Apr 2026 09:26:05 GMT</lastBuildDate><atom:link href="https://blog.zcsouls.com/feed" rel="self" type="application/rss+xml"/><pubDate>Sat, 18 Apr 2026 09:26:05 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[如何在 NAT1 下实现无感 PLEX 外网访问]]></title><description><![CDATA[<link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306221315065.webp"/><link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306221333370.webp"/><link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306221350532.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/tech/plex_nat1_remote_access">https://blog.zcsouls.com/posts/tech/plex_nat1_remote_access</a></blockquote><div><h2 id="">效果</h2><p>能在没有公网，仅拥有 NAT1 的情况下，做到无感 PLEX 外网访问</p><h2 id="">前提</h2><ul><li>确保路由器的 NAT 类型为 NAT1,并且要求 TCP 的 NAT 类型也为 NAT1</li><li>主路由场景下基本没什么大问题，如果在旁路由场景下可能需要为旁路由开启 DMZ，此外，<code>OpenClash</code>等科学插件也有影响</li><li>安装 Lucky，这里不多赘述，自行解决</li></ul><h3 id="">相关链接</h3><p><a href="https://github.com/gdy666/lucky">https://github.com/gdy666/lucky</a></p><ul><li><a href="https://python-plexapi.readthedocs.io/en/latest/introduction.html">Python-plexapi</a></li></ul><h2 id="">配置</h2><p><strong>脚本配置</strong></p><ul><li>以 <strong>Openwrt</strong> 为例，首先确保安装Python，随后安装下列库</li></ul><pre class="language-shell lang-shell"><code class="language-shell lang-shell">pip3 install plexapi
</code></pre>
<ul><li>根据其中需要修改的四行代码，修改为自己的实际参数，随后复制并建立一个<code>.py</code>文件，例如 <code>modify_port.py</code>，放置于任意位置，例如<code>/root</code>路径下</li></ul><p><strong>这是需要修改的内容</strong></p><pre class="language-text lang-text"><code class="language-text lang-text"># Plex 账号信息
PLEX_USERNAME = &quot;example@qq.com&quot;
PLEX_PASSWORD = &quot;password&quot;

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

TOKEN_FILE = &quot;/root/plex_token.json&quot;  # 保存 PLEX Token 的路径
</code></pre>
<p><strong>这是脚本代码</strong></p><pre class="language-python lang-python"><code class="language-python lang-python">import os
import sys
import json
import requests
from plexapi.server import PlexServer

# Plex 账号信息
PLEX_USERNAME = &quot;example@qq.com&quot;
PLEX_PASSWORD = &quot;password&quot;

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

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

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

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

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

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

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

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

if __name__ == &quot;__main__&quot;:
    # 第一步：解析命令行参数，获取新的端口号
    if len(sys.argv) &lt; 2:
        print(&quot;用法: python3 modify.py &lt;new_port&gt;&quot;)
        sys.exit(1)

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

    # 第二步：定义令牌存储文件
    TOKEN_FILE = &quot;/root/plex_token.json&quot;  # 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(&quot;获取有效令牌失败。&quot;)
            sys.exit(1)

    # 第五步：使用 plexapi 连接到 Plex 服务器并修改手动端口
    try:
        plex = PlexServer(PLEX_SERVER_BASEURL, PLEX_TOKEN)
        print(&quot;成功连接到 Plex 服务器！&quot;)
  
        # 修改手动端口映射（使用传入的端口号）
        modify_port(plex, NEW_PORT)
    except Exception as e:
        print(f&quot;连接 Plex 服务器或修改设置时发生错误: {str(e)}&quot;)
</code></pre>
<p><strong>Lucky 配置</strong></p><p><img src="https://s3.zcsouls.com:443/image/blog/20250306221315065.webp" alt="LUCKY"/></p><p>创建一个 TCP 穿透规则，这里我指定了一个空闲端口为 13333，并且不使用 LUCKY 的内置端口转发。开启自定义脚本触发，代码如下：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">python3 /root/modify_port.py ${port}

if [ $? -ne 0 ]; then
    echo &quot;Python script execution failed with exit code $?.&quot;
fi
</code></pre>
<p>注意此处代码的 /root/modify_port.py 就是刚刚的python执行脚本的实际路径。</p><p>随后确认即可，规则创建关闭后稍时即可打洞成功。</p><p><strong>端口转发</strong></p><p>由于我们刚刚指定了端口，并且没有使用Lucky内置的端口转发，因此我们需要用防火墙配置手动端口转发</p><p><img src="https://s3.zcsouls.com:443/image/blog/20250306221333370.webp" alt="端口转发"/></p><p>如果你是主路由，源区域应该是防火墙的“WAN”区域，我是旁路由，所以源区域为LAN</p><p>外部端口就是刚刚打洞绑定的端口，例如我刚刚在 LUCKY 配置了13333端口</p><p>目前区域即可 LAN，内部 IP 地址即为 PLEX 所在主机 IP，内部端口通常为 PLEX Server 默认端口32400</p><h2 id="">常见问题</h2><ul><li>在配置前可单独调试脚本，确保脚本正常运作，脚本调试命令为：</li></ul><pre class="language-shell lang-shell"><code class="language-shell lang-shell">python3 modify_port.py &lt;port&gt;
</code></pre><ul><li>旁路由的可能额外操作
LUCKY 位于旁路由，并且使用了 Openclash，即使配置了旁路由为 DMZ，但是 TCP 流量经过了 Openclash，因此导致了 TCP 的 NAT 类型不为 NAT1。</li></ul><p>解决方案有下列几种：</p><ol start="1"><li>通过 Openclash 的仅允许常用端口流量功能，可以让打洞的流量不经过 Openclash，即不包含3478端口流量</li><li><p>通过 Openclash 的黑白名单功能中的绕过核心的来源端口功能</p><p><img src="https://s3.zcsouls.com:443/image/blog/20250306221350532.webp" alt="旁路由"/></p></li></ol><p>设置几个打洞时绑定的预设端口，这些端口流量就不会经过 Openclash 了，但配置中也指出了，Fake ip模式下只能过滤纯 IP 类型请求。</p><p>其它请自行发挥，包括但不限于使用Openclash的开发者选项，或者修改防火墙来实现</p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/tech/plex_nat1_remote_access#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/tech/plex_nat1_remote_access</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/tech/plex_nat1_remote_access</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Mon, 28 Oct 2024 14:08:59 GMT</pubDate></item><item><title><![CDATA[Switch版 Steins;Gate - Divergencies Assort 汉化补丁]]></title><description><![CDATA[<div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/other/ns_sgda_chs">https://blog.zcsouls.com/posts/other/ns_sgda_chs</a></blockquote><div><h2 id="">前言</h2><p>自移植过 <code>NS</code>的 <code>SG0</code>和 <code>SG:MDE</code>的汉化后，一直没有时间着手分歧组合的汉化，不过好在最终还是解决了一些技术上的问题实现了汉化。</p><p>分歧组合包含三部作品，<code>SG0</code>、<code>SG:MDE</code>、<code>SG:LBP</code>，由于前两部在 NS 上有单独版本并且已经被我汉化，所以这次的分歧组合理论上只要针对其中的 <code>SG:LBP</code>进行汉化即可。不过实际上遇到的问题远比我想象的复杂，三部作品中的菜单类文本是共用了一个文字脚本文件，尤其是其中的“人名”，由于三部作品汉化并不是统一的，为了规范并统一这些名称，我只能手动纠正，这确实很折磨人。</p><ul><li>「命运石之门0」-&gt; 官方汉化</li><li>「命运石之门：比翼恋理的爱人」 -&gt; 民间汉化组</li><li>「命运石之门：线形拘束的表征图」 -&gt; 民间汉化组</li></ul><p>其中汉化文本，尤其是来自那些汉化组的，在测试的过程中我发现了大量的错别字，以及一系列命名规范的问题，我也尽力尝试进行了修正，但是不能保证完全没有任何错误。</p><h2 id="">下载</h2><p><a href="https://github.com/fl0w1nd/NS_Steins-Gate-Divergencies-Assort-CHS">https://github.com/fl0w1nd/NS_Steins-Gate-Divergencies-Assort-CHS</a></p><p>其它发布网站：<a href="https://www.tekqart.com/thread-390498-1-1.html?_dsign=3a813bbc">品技</a></p><h2 id="">使用方法</h2><p>需要一台能够运行 Atmosphere 自制固件（CFW）的 Nintendo Switch 主机。</p><p>从<a href="https://github.com/fl0w1nd/NS_Steins-Gate-Divergencies-Assort-CHS/releases">Releases</a>下载 <code>Text.Only.zip</code>，然后将补丁中的 <code>0100BE400CA2E000 </code>文件夹放到 <code>SD:/atmosphere/contents/</code>文件夹下。如果你需要CG汉化（部分汉化以及英文化）的请继续下载 <code>bg.zip </code>，同样将补丁中的 <code>0100BE400CA2E000 </code>文件夹放到 <code>SD:/atmosphere/contents/</code>文件夹下。</p><blockquote class="markdown-alert-note"><header>NOTE</header><p>Release 包含两个文件，其中 Text Only 为主体翻译，包含游戏中所有的文本翻译，以及部分菜单翻译。 bg 是游戏的CG汉化包，CG 汉化中仅 SG0 为中文汉化，其余两部作品中包含文字部分的内容用英文版进行替换。</p></blockquote>
<p><mark class="rounded-md"><span class="px-1">如何确定你是否需要 CG 包？</span></mark></p><ol start="1"><li>如果你不在乎补丁的大小，并且希望分歧组合中的 SG0 也能体验到接近于官方中文版本的体验，并且其余两部作品需要所有文字 CG 都以英文版的方式显示，你可以使用 CG 包。</li><li>具有一定日语能力，或者你不在乎其中几张 CG 是否为中文，那么你可以仅安装本体汉化。</li></ol><h2 id="">优化</h2><p>如果你热爱该作品，并且有很好的 PS 基础，你可以考虑实现更加完善的汉化。例如菜单汉化，
Github仓库中的 <code>system</code>目录下是游戏内的所有菜单的图像资源，你可以提交 PR，实现更完善的汉化。</p><h2 id="">致谢</h2><p><a href="https://github.com/wetor/MagesTools">https://github.com/wetor/MagesTools</a></p><p><a href="https://github.com/CommitteeOfZero/mgsfontgen-dx">https://github.com/CommitteeOfZero/mgsfontgen-dx</a></p><p><a href="https://github.com/morkt/GARbro">https://github.com/morkt/GARbro</a></p><ul><li>CRI File System Tools</li></ul><h2 id="">免责声明</h2><p>最后再说一句那啥，该补丁仅用于学习交流使用，请不要用于商业用途。</p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/other/ns_sgda_chs#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/other/ns_sgda_chs</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/other/ns_sgda_chs</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Sun, 09 Jun 2024 13:07:51 GMT</pubDate></item><item><title><![CDATA[Docker PHP8 容器挖矿病毒]]></title><description><![CDATA[<link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306220001806.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/other/docker-php8-container-mining-virus">https://blog.zcsouls.com/posts/other/docker-php8-container-mining-virus</a></blockquote><div><h2 id="">前言</h2><p>今天登录 VPS 时意外发现CPU占用 100%，察觉到意外的我立马检查了相关应用，最后定位到了 Docker 中的 PHP8 容器。容器占用了几乎所有的 CPU 资源和内存，随即我对此展开了调查。</p><h2 id="">日志分析</h2><pre class=""><code class="">[07-Jun-2024 15:02:57] NOTICE: fpm is running, pid 1
[07-Jun-2024 15:02:57] NOTICE: ready to handle connections
172.18.0.1 -  07/Jun/2024:15:03:23 +0800 &quot;GET /index.php&quot; 200
172.18.0.1 -  07/Jun/2024:15:04:57 +0800 &quot;GET /index.php&quot; 200
chattr: setting flags on /tmp/: Operation not permitted
chattr: setting flags on /var/tmp/: Operation not permitted
chattr: setting flags on /var/spool/cron: Operation not permitted
chattr: can&#x27;t open &#x27;/var/spool/cron/crontabs&#x27;: Symbolic link loop
chattr: can&#x27;t stat &#x27;/etc/crontab&#x27;: No such file or directory
sh: ufw: not found
sh: iptables: not found
sh: sudo: not found
sh: can&#x27;t create /proc/sys/kernel/nmi_watchdog: Read-only file system
sh: can&#x27;t create /etc/sysctl.conf: Permission denied
userdel: user &#x27;akay&#x27; does not exist
userdel: user &#x27;vfinder&#x27; does not exist
chattr: can&#x27;t stat &#x27;/root/.ssh/&#x27;: Permission denied
chattr: can&#x27;t stat &#x27;/root/.ssh/authorized_keys&#x27;: Permission denied
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
crontab: must be suid to work properly
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
sed: /tmp/.X11-unix/01: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.X11-unix/01&#x27;: No such file or directory
sed: /tmp/.X11-unix/11: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.X11-unix/11&#x27;: No such file or directory
sed: /tmp/.X11-unix/22: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.X11-unix/22&#x27;: No such file or directory
sed: /tmp/.systemd.1: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.systemd.1&#x27;: No such file or directory
sed: /tmp/.systemd.2: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.systemd.2&#x27;: No such file or directory
sed: /tmp/.systemd.3: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.systemd.3&#x27;: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.systemd.1&#x27;: No such file or directory
sh: you need to specify whom to kill
cat: can&#x27;t open &#x27;/tmp/.systemd.2&#x27;: No such file or directory
sh: you need to specify whom to kill
cat: can&#x27;t open &#x27;/tmp/.systemd.3&#x27;: No such file or directory
sh: you need to specify whom to kill
sed: /tmp/.pg_stat.0: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.pg_stat.0&#x27;: No such file or directory
sed: /tmp/.pg_stat.1: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.pg_stat.1&#x27;: No such file or directory
sed: /home/www-data/data/./oka.pid: No such file or directory
cat: can&#x27;t open &#x27;/home/www-data/data/./oka.pid&#x27;: No such file or directory
sed: /tmp/.ICE-unix/d: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.ICE-unix/d&#x27;: No such file or directory
sed: /tmp/.ICE-unix/m: No such file or directory
cat: can&#x27;t open &#x27;/tmp/.ICE-unix/m&#x27;: No such file or directory
ps: unrecognized option: w
BusyBox v1.36.1 (2023-11-07 18:53:09 UTC) multi-call binary.
Usage: ps [-o COL1,COL2=HEADER] [-T]
Show list of processes
    -o COL1,COL2=HEADER    Select columns for display
    -T            Show threads
ps: unrecognized option: w
BusyBox v1.36.1 (2023-11-07 18:53:09 UTC) multi-call binary.
Usage: ps [-o COL1,COL2=HEADER] [-T]
Show list of processes
    -o COL1,COL2=HEADER    Select columns for display
    -T            Show threads
kill: invalid number &#x27;USER&#x27;
grep: bad regex &#x27;kworker -c\&#x27;: Trailing backslash
kill: invalid number &#x27;USER&#x27;
kill: invalid number &#x27;www-data&#x27;
kill: invalid number &#x27;www-data&#x27;
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
netstat: showing only processes with your user ID
sh: systemctl: not found
killall: log_rot: no process killed
chattr: can&#x27;t stat &#x27;/etc/ld.so.preload&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/1.sh&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/1.sh.1&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/1.sh.2&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/1.sh.3&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/3.sh&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/3.sh.1&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/3.sh.2&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/opt/atlassian/confluence/bin/3.sh.3&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/var/tmp/lib&#x27;: No such file or directory
rm: can&#x27;t remove &#x27;/var/tmp/.lib&#x27;: No such file or directory
chattr: can&#x27;t stat &#x27;/tmp/lok&#x27;: No such file or directory
chmod: /tmp/lok: No such file or directory
sh: docker: not found
sh: docker: not found
sh: docker: not found
sh: setenforce: not found
sh: can&#x27;t create /etc/selinux/config: nonexistent directory
sh: service: not found
sh: systemctl: not found
sh: service: not found
sh: systemctl: not found
/tmp/kinsing is b3039abf2ad5202f4a9363b418002351
crontab: must be suid to work properly
crontab: must be suid to work properly
144.202.29.195 -  07/Jun/2024:15:09:55 +0800 &quot;POST /usr/local/lib/php/PEAR.php&quot; 200
</code></pre>
<p>可以看到，容器日志中有着很多权限错误，<code>/tmp/kinsing is b3039abf2ad5202f4a9363b418002351</code>
这一行中的kinsing是一个知名挖矿病毒 <code>kdevtmpfsi</code>的守护进程。</p><p><img src="https://s3.zcsouls.com:443/image/blog/20250306220001806.webp" alt="系统占用"/></p><p>随即我使用 <code>ssh</code>登录服务器，使用 <code>top</code>命令检测系统占用，果不其然，挖矿进程正占用了系统的主要资源。</p><h2 id="">解决与反思</h2><p>首先我尝试了停止 PHP 容器，随后检测发现 <code>kdevtmpfsi</code>的进程停止了，因此可以判断病毒仅存在于容器内。最后我重新构建了 PHP 容器，一切都得到解决，病毒进程也不在出现了。</p><p>我在网上查询相关的信息，发现有很多人都中过这个挖矿病毒，大多数人都是由于将 php-fpm 的9000端口暴露在了公网造成的，这是由于 Docker 在映射端口时需要指定127.0.0.1:9000-&gt;9000才是将端口映射在本地，如果映射到 0.0.0.0:9000 的话会绕过 ufw 直接暴露在公网。但问题是，我的服务器不仅有本地的防火墙，还有服务商那里的防火墙，因此不可能存在端口暴露在公网这种问题。此外，由于我服务器 SSH 登录方式采用密钥登录，也几乎排除了服务器被破解登录的可能性。</p><p>排除了所有的可能性之后，我只能认为是 Typecho 博客的的漏洞了，目前的解决措施是使用了 1panel 的 WAF 功能进行 XSS 防御和 SQL 注入防御。</p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/other/docker-php8-container-mining-virus#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/other/docker-php8-container-mining-virus</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/other/docker-php8-container-mining-virus</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Fri, 07 Jun 2024 13:59:36 GMT</pubDate></item><item><title><![CDATA[删除 Typecho 中未关联的标签]]></title><description><![CDATA[<div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/archieve/delete_typecho_unlinked_tags">https://blog.zcsouls.com/posts/archieve/delete_typecho_unlinked_tags</a></blockquote><div><h2 id="">前言</h2><p>由于部分文章的删除，导致了博客的标签中遗留一些无用的标签，虽然在网页前端看不到，但是它实际上还是存在于数据库中，而且还被编入了索引。</p><p>例如：https://www.zcsouls.com/tag/{标签}/</p><p>因此我们可以通过操作数据库来删除这些“牛皮癣”。</p><h2 id="">操作步骤</h2><h3 id="-1-">步骤 1: 访问数据库</h3><p>使用数据库管理工具（如phpMyAdmin、Adminer等）登录到你的数据库。</p><h3 id="-2-">步骤 2: 确认标签和文章关联的表</h3><p>Typecho通常使用以下两张表来存储标签和文章的信息：</p><ul><li><code>typecho_metas</code>：存储标签（和分类）的信息。</li><li><code>typecho_relationships</code>：存储文章和标签（或分类）之间的关联关系。</li></ul><h3 id="-3-sql">步骤 3: 执行SQL查询</h3><p>以下的SQL查询将帮助你找出没有关联任何文章的标签，并删除它们。这里的查询假设你的表前缀是 <code>typecho_</code>，这是Typecho的默认设置。如果你的表前缀不同，请相应修改。</p><pre class="language-sql lang-sql"><code class="language-sql lang-sql">DELETE FROM typecho_metas 
WHERE type = &#x27;tag&#x27; 
AND mid NOT IN (
    SELECT mid FROM typecho_relationships
);
</code></pre>
<h3 id="">详细解释</h3><ul><li><code>DELETE FROM typecho_metas WHERE type = &#x27;tag&#x27;</code>：这一部分指定要删除来自 <code>typecho_metas</code>表中的记录，且这些记录的类型（<code>type</code>）为“tag”，即标签。</li><li><code>AND mid NOT IN (SELECT mid FROM typecho_relationships)</code>：这里使用子查询来找出 <code>typecho_relationships</code>表中存在的所有 <code>mid</code>（即标签的ID）。<code>NOT IN</code>确保我们删除的是那些在关联表中没有出现过的标签的 <code>mid</code>。</li></ul><h3 id="-4-">步骤 4: 检查和维护</h3><ul><li>在执行删除操作前，可以先运行一个SELECT查询来查看将要被删除的标签：
<code>sql
SELECT * FROM typecho_metas 
WHERE type = &#x27;tag&#x27; 
AND mid NOT IN (
    SELECT mid FROM typecho_relationships
);
</code></li><li>确保上述查询只显示了那些确实没有被任何文章引用的标签后，再执行删除操作。</li></ul><h3 id="">最后的提醒</h3><p>操作数据库时一定要小心谨慎，确保所有操作都有备份！！！</p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/archieve/delete_typecho_unlinked_tags#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/archieve/delete_typecho_unlinked_tags</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/archieve/delete_typecho_unlinked_tags</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Thu, 23 May 2024 07:41:38 GMT</pubDate></item><item><title><![CDATA[Portainer 通过配置 TLS 加密实现 Docker API 安全管理]]></title><description><![CDATA[<link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306215058451.webp"/><link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306215117513.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/tech/docker-tls-secure-setup">https://blog.zcsouls.com/posts/tech/docker-tls-secure-setup</a></blockquote><div><h2 id="">前言</h2><p>Docker 拥有 API 功能，可以通过 Portainer 远程连接进行可视化管理，但在没有加密的情况下比较危险，因此需要配置TLS 加密来保障 Docker API 通信的安全性。通过开启 TLS 防止未经许可的客户端访问服务端节点，保障其系统安全性。</p><h2 id="">开始</h2><h3 id="-tls-">创建 TLS 证书</h3><pre class="language-bash lang-bash"><code class="language-bash lang-bash">#!/bin/bash
# 
# -------------------------------------------------------------
# 自动创建 Docker TLS 证书
# -------------------------------------------------------------

# 以下是配置信息
# --[BEGIN]------------------------------

PASSWORD=&quot;your code&quot;
COUNTRY=&quot;CN&quot;
STATE=&quot;your state&quot;
CITY=&quot;your city&quot;
ORGANIZATION=&quot;your org&quot;
ORGANIZATIONAL_UNIT=&quot;your org unit&quot;
EMAIL=&quot;your email&quot;

# --[END]--

CODE=&quot;docker_api&quot;
IP=`curl ip.sb -4`
COMMON_NAME=&quot;$IP&quot;

# Generate CA key
openssl genrsa -aes256 -passout &quot;pass:$PASSWORD&quot; -out &quot;ca-key-$CODE.pem&quot; 4096
# Generate CA
openssl req -new -x509 -days 365 -key &quot;ca-key-$CODE.pem&quot; -sha256 -out &quot;ca-$CODE.pem&quot; -passin &quot;pass:$PASSWORD&quot; -subj &quot;/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL&quot;
# Generate Server key
openssl genrsa -out &quot;server-key-$CODE.pem&quot; 4096

# Generate Server Certs.
openssl req -subj &quot;/CN=$COMMON_NAME&quot; -sha256 -new -key &quot;server-key-$CODE.pem&quot; -out server.csr

echo &quot;subjectAltName = IP:$IP,IP:127.0.0.1&quot; &gt;&gt; extfile.cnf
echo &quot;extendedKeyUsage = serverAuth&quot; &gt;&gt; extfile.cnf

openssl x509 -req -days 365 -sha256 -in server.csr -passin &quot;pass:$PASSWORD&quot; -CA &quot;ca-$CODE.pem&quot; -CAkey &quot;ca-key-$CODE.pem&quot; -CAcreateserial -out &quot;server-cert-$CODE.pem&quot; -extfile extfile.cnf


# Generate Client Certs.
rm -f extfile.cnf

openssl genrsa -out &quot;key-$CODE.pem&quot; 4096
openssl req -subj &#x27;/CN=client&#x27; -new -key &quot;key-$CODE.pem&quot; -out client.csr
echo extendedKeyUsage = clientAuth &gt;&gt; extfile.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -passin &quot;pass:$PASSWORD&quot; -CA &quot;ca-$CODE.pem&quot; -CAkey &quot;ca-key-$CODE.pem&quot; -CAcreateserial -out &quot;cert-$CODE.pem&quot; -extfile extfile.cnf

rm -vf client.csr server.csr

chmod -v 0400 &quot;ca-key-$CODE.pem&quot; &quot;key-$CODE.pem&quot; &quot;server-key-$CODE.pem&quot;
chmod -v 0444 &quot;ca-$CODE.pem&quot; &quot;server-cert-$CODE.pem&quot; &quot;cert-$CODE.pem&quot;

# 打包客户端证书
mkdir -p &quot;tls-client-certs-$CODE&quot;
cp -f &quot;ca-$CODE.pem&quot; &quot;cert-$CODE.pem&quot; &quot;key-$CODE.pem&quot; &quot;tls-client-certs-$CODE/&quot;
cd &quot;tls-client-certs-$CODE&quot;
tar zcf &quot;tls-client-certs-$CODE.tar.gz&quot; *
mv &quot;tls-client-certs-$CODE.tar.gz&quot; ../
cd ..
rm -rf &quot;tls-client-certs-$CODE&quot;

# 拷贝服务端证书
mkdir -p /srv/certs.d
cp &quot;ca-$CODE.pem&quot; &quot;server-cert-$CODE.pem&quot; &quot;server-key-$CODE.pem&quot; &quot;tls-client-certs-$CODE.tar.gz&quot; /srv/certs.d/
</code></pre>
<p>修改上面的配置信息，将上述脚本保存为一个 <code>.sh</code> 文件，并在命令行执行 <code>bash xxx.sh</code> 以运行该脚本。运行后将在 <code>/srv/certs.d</code> 目录下生成证书，其中包括 <code>tls-client-certs-docker_api.tar.gz</code> ，该文件保存着客户端访问 Docker API 所需的证书，请下载下来并安全和妥善地保存。</p><h3 id="-docker-api">开启 Docker API</h3><p>首先打开终端并执行以下命令：</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">vim /lib/systemd/system/docker.service
</code></pre>
<p><img src="https://s3.zcsouls.com:443/image/blog/20250306215058451.webp" alt="添加"/></p><p>在打开的 Docker 服务文件中查找 ExecStart 行</p><p>在 ExecStart 行的后面添加以下选项：</p><pre class="language-plaintext lang-plaintext"><code class="language-plaintext lang-plaintext">-H=tcp://0.0.0.0:2376 --tlsverify --tlscacert=/srv/certs.d/ca-docker_api.pem --tlscert=/srv/certs.d/server-cert-docker_api.pem --tlskey=/srv/certs.d/server-key-docker_api.pem
</code></pre>
<p>最后，执行以下命令重新加载服务并重启 Docker：</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">systemctl daemon-reload &amp;&amp; service docker restart
</code></pre>
<h3 id="">验证</h3><p>此时，我们需要验证 Docker API 是否能够访问，且是否只能通过加密访问。</p><p>首先执行 <code>docker -H=127.0.0.1:2376 info</code>，一般来说会返回：</p><pre class="language-plaintext lang-plaintext"><code class="language-plaintext lang-plaintext">Client:
Context:    default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
Server:
ERROR: Error response from daemon: Client sent an HTTP request to an HTTPS server.
errors pretty printing info
</code></pre>
<p>这是因为没有通过 tls 去访问，此时改用 <code>docker -H=127.0.0.1:2376 --tlsverify info</code>，会出现下面的错误：</p><pre class="language-plaintext lang-plaintext"><code class="language-plaintext lang-plaintext">unable to resolve docker endpoint: open /root/.docker/ca.pem: no such file or directory
</code></pre>
<p>这是由于目前没有在对应的用户文件夹下配置证书，我们可以执行以下命令：</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">mkdir ~/.docker &amp;&amp; \
tar -zxvf /srv/certs.d/tls-client-certs-docker_api.tar.gz -C ~/.docker &amp;&amp; \
mv ~/.docker/ca-docker_api.pem ~/.docker/ca.pem &amp;&amp; \
mv ~/.docker/cert-docker_api.pem ~/.docker/cert.pem &amp;&amp; \
mv ~/.docker/key-docker_api.pem ~/.docker/key.pem
</code></pre>
<p>完成后再执行一遍 <code>docker -H=127.0.0.1:2376 --tlsverify info</code> 即可获取信息了，至此验证完成。</p><h3 id="-portainer">配置 Portainer</h3><p>打开 Portainer，进入 Environments：</p><p>点击右上角的 Add environment 添加节点，并在随后的向导中选择 API。</p><p>将环境 URL 或者 Docker API URL 中的端口从 2375 改为 2376。然后将 TLS 的 Switch 打开，即可看到相关的 TLS 配置项，我们在第一步的时候下载了一份文件，解压后根据对应关系上传即可。</p><p><img src="https://s3.zcsouls.com:443/image/blog/20250306215117513.webp" alt="Portainer配置"/></p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/tech/docker-tls-secure-setup#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/tech/docker-tls-secure-setup</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/tech/docker-tls-secure-setup</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Sat, 23 Sep 2023 13:49:58 GMT</pubDate></item><item><title><![CDATA[Switch版 SG0 汉化补丁]]></title><description><![CDATA[<div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/other/nssg0_chs">https://blog.zcsouls.com/posts/other/nssg0_chs</a></blockquote><div><h2 id="">汉化说明</h2><p>汉化文本来源于<mark class="rounded-md"><span class="px-1">官方中文</span></mark></p><p>汉化所使用的工具:</p><ul><li>文本导入导出工具:</li></ul><p><a href="https://github.com/wetor/MagesTools">https://github.com/wetor/MagesTools</a></p><ul><li>CPK解包工具 - <mark class="rounded-md"><span class="px-1">CRI File System Tools</span></mark></li></ul><h2 id="">使用方法</h2><p>大气层系统解压后将 <code>010037700E9B8000</code> 文件夹放置于<code>atmosphere/contents</code>目录下</p><h2 id="">注意事项</h2><p>系统语言不能设置为日文，因为该汉化补丁基于英文版制作</p><p>由于使用了 OCR 扫描制作字库，可能存在部分错别字，游玩过程中若发现错别字，可反馈至邮箱 <code>fl0w1nd@qq.com</code></p><h2 id="">下载</h2><p><a href="https://github.com/fl0w1nd/sg0-ns-chs">https://github.com/fl0w1nd/sg0-ns-chs</a></p><h2 id="">其它</h2><p>禁止将该补丁与游戏本体进行打包，转载请注明来源</p><p>本补丁其它发布地址:
<a href="https://www.tekqart.com/thread-356273-1-1.html">品技</a></p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/other/nssg0_chs#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/other/nssg0_chs</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/other/nssg0_chs</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Fri, 01 Sep 2023 12:56:21 GMT</pubDate></item><item><title><![CDATA[ZeroTier Moon 节点部署]]></title><description><![CDATA[<link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306213246279.webp"/><link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306213314573.webp"/><link rel="preload" as="image" href="https://s3.zcsouls.com:443/image/blog/20250306213342805.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/tech/zerotier_moon">https://blog.zcsouls.com/posts/tech/zerotier_moon</a></blockquote><div><h2 id="moonmoon">Moon是什么，为什么需要Moon？</h2><p>ZeroTier 通过自己的多个根服务器帮助我们建立虚拟的局域网，让虚拟局域网内的各台设备可以打洞直连。这些根服务器的功能有些类似于通过域名查询找到服务器地址的 DNS 服务器，它们被称为 Planet. 然而这里存在一个非常严重的问题，就是 Zerotier 的官方行星服务器都部署在国外，从国内访问的时候延迟很大，甚至在网络高峰期的时候都没法访问，这也会导致我们的虚拟局域网变得极不稳定，经常掉链子。</p><p>为了应对网络链接的延迟和不稳定，提高虚拟局域网的速度和可靠性，Zerotier 允许我们建立自己的 moon 卫星中转服务器。</p><h2 id="">搭建流程(省略服务器购买相关基础说明)</h2><h3 id="-zerotier">配置 ZEROTIER</h3><ul><li>安装</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">curl -s https://install.zerotier.com/ | sudo bash
</code></pre>
<p><img src="https://s3.zcsouls.com:443/image/blog/20250306213246279.webp" alt="安装流程"/></p><p>显示 Success 后安装成功</p><ul><li>启动</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">zerotier-one -d
</code></pre>
<ul><li>加入</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo zerotier-cli join xxxxxxxxxxxxxxxx
</code></pre>
<p>xxxxxxxxxxxxx为 zerotier 官网创建的网络id</p><p>加入成功后显示 200 join ok
之后前往 ZEROTIER 官网授权客户端</p><h3 id="-moon-">配置 MOON 节点</h3><ul><li>生成一个 moon 文件</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">cd /var/lib/zerotier-one
zerotier-idtool initmoon identity.public &gt; moon.json
</code></pre>
<ul><li>编辑<code>moon.json</code>文件
使用 vim 或 nano 以及宝塔图形化等编辑器编辑 moon.json 文件</li></ul><p><img src="https://s3.zcsouls.com:443/image/blog/20250306213314573.webp" alt="配置moon.json文件"/></p><p>如图，在stableEndpoints后的方括号内输入&quot;你的服务器公网ip&quot;/9993
包括英文双引号，随后保存该文件。并执行以下命令：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">zerotier-idtool genmoon moon.json
</code></pre>
<p>会显示一行 wrote 开头的代码，包括一串 <code>xxxxxxxxxxxxxxxxxxx.moon</code>文本，其中xxxxxxxxxxxxxxx为生成的随机 id。</p><ul><li>创建<code>moons.d</code>目录</li></ul><p>在该目录下创建 moons.d 目录</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo mkdir moons.d
</code></pre>
<ul><li>移动配置文件</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo mv xxxxxxxxxxxxxx.moon moons.d/
</code></pre>
<p>xxxxxxxxxxxxxx为上文生成的id。</p><ul><li>重启 ZEROTIER 服务端</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo systemctl restart zerotier-one
</code></pre>
<h2 id="">客户端配置</h2><h3 id="windows-">Windows 客户端</h3><p>在 Zerotier 默认安装路径<code>C:\ProgramData\ZeroTier\One</code>下新建 moons.d 文件夹，并将服务端得到的<code>.moon</code>后缀文件放入，随后在 windows 任务管理器中重新启动<code>ZeroTierOneService</code>服务进程。</p><p>随后在CMD中运行 <code>zerotier-cli listpeers</code>命令</p><p><img src="https://s3.zcsouls.com:443/image/blog/20250306213342805.webp" alt="cmd命令"/></p><p>若显示公网<code>ip/9993</code>的 MOON 节点则代表正确。</p><h3 id="linux">LINUX客户端</h3><p>Linux 客户端需要在<code>var/lib/zerotier</code>路径下新建 moos.d 文件夹，和 windows 一样将 .moon 后缀的文件放到里面，随后使用和 windows 相同的命令 <code>zerotier-cli listpeers</code>检查是否生效。</p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/tech/zerotier_moon#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/tech/zerotier_moon</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/tech/zerotier_moon</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Tue, 21 Mar 2023 13:25:22 GMT</pubDate></item><item><title><![CDATA[TeamSpeak 部署教程]]></title><description><![CDATA[<link rel="preload" as="image" href="https://s3.zcsouls.com/image/blog/20250306175633918.webp"/><link rel="preload" as="image" href="https://s3.zcsouls.com/image/blog/20250306175707601.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.zcsouls.com/posts/tech/ts3">https://blog.zcsouls.com/posts/tech/ts3</a></blockquote><div><h2 id="">前言</h2><p>TeamSpeak 是全球流行的团队语音通讯工具软件，常用于游戏、会议团队语音沟通，并提供文字聊天、文件共享功能，所有数据加密传输。
由于 YY语音 有很多广告，Discord 由于服务器在国外延迟比较高，因此转而使用 Teamspeak 通讯获得更好的通讯体验。</p><blockquote class="markdown-alert-note"><header>NOTE</header><p>本文将演示如何在 Centos7 系统下搭建 Teamspeak3 服务端。</p></blockquote>
<h2 id="">普通搭建</h2><h3 id="">更新系统</h3><ul><li><p>更新系统</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">yum update -y
</code></pre>
</li><li><p>安装必要组件</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">yum install vim wget perl tar net-tools bzip2 -y
</code></pre>
</li></ul><h3 id="">开始部署</h3><p>::: banner {error}
为保证安全，官方建议不要使用 root 账号搭建
:::</p><ul><li><p>首先新建一个用户，名为 teamspeak</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">useradd teamspeak
passwd teamspeak
</code></pre>
</li><li><p>进入 opt 目录</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">cd /opt
</code></pre>
</li><li><p>获取最新服务端 (目前最新版本为 3.13.7) <a href="https://www.teamspeak.com/zh-CN/downloads/#server">官网服务端下载</a></p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">wget https://files.teamspeak-services.com/releases/server/3.13.7/teamspeak3-server_linux_amd64-3.13.7.tar.bz2
</code></pre>
</li><li><p>解压最新服务端软件包并删除压缩包</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">tar -xjvf teamspeak3-server_linux_amd64-3.13.7.tar.bz2 &amp;&amp; rm teamspeak3-server_linux_amd64-3.13.7.tar.bz2
</code></pre>
</li><li><p>赋予普通用户 <code>teamspeak</code> 权限，并进入该目录</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">chown -R teamspeak:teamspeak teamspeak3-server_linux_amd64 &amp;&amp; cd /opt/teamspeak3-server_linux_amd64 &amp;&amp; su teamspeak
</code></pre>
</li></ul><h3 id="">配置与运行</h3><ul><li><p>同意 <code>TeamSpeak</code> 许可条款</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">touch .ts3server_license_accepted
</code></pre>
</li><li><p>自动配置数据库并启动 <code>TeamSpeak</code> 服务器</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">./ts3server_startscript.sh start
</code></pre>
</li><li><p>屏幕上会出现两条 <code>IMPORTANT</code> 的信息，请注意保管并记牢！</p><ul><li><code>serveradmin</code> 为服务端查询管理账号，<code>password</code> 即为服务端查询登录密码</li><li><code>Token</code> 是激活服务器管理员的重要凭证！</li></ul></li><li><p><img src="https://s3.zcsouls.com/image/blog/20250306175633918.webp"/></p></li></ul><h3 id="">放行防火墙</h3><blockquote class="markdown-alert-note"><header>NOTE</header><p>管理面板放行端口较为简单这里不再提及，演示使用 Centos7 防火墙放行端口</p></blockquote>
<ul><li><p>首先切换到管理员用户</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">su root
</code></pre>
</li><li><p>找到 <code>default zone</code></p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">firewall-cmd --get-default-zone
</code></pre>
</li><li><p>打开与 <code>TeamSpeak</code> 服务相关的端口</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">firewall-cmd --zone=public --permanent --add-port=9987/udp
firewall-cmd --zone=public --permanent --add-port=10011/tcp
firewall-cmd --zone=public --permanent --add-port=30033/tcp
</code></pre>
<p>9987/udp for Voice.
30033/tcp for Filetransfer.
10011/tcp for ServerQuery.</p></li><li><p>重载 <code>firewalld</code> 以使其生效</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">firewall-cmd --reload
</code></pre>
</li></ul><h3 id="">自启动配置</h3><ul><li><p>编辑服务项配置文件</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">vi /lib/systemd/system/teamspeak.service
</code></pre>
</li><li><p>在该文件中写入如下内容：（按 <code>i</code> 进入编辑模式，编辑完成后按 <code>ESC</code> 退出编辑模式，接着输入 <code>:wq</code> 保存并退出 vi 编辑器）</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">[Unit]
Description=Teamspeak, The most superior online voice communication solution.
After=network.target

[Service]
User=teamspeak
Group=teamspeak
WorkingDirectory=/opt/teamspeak3-server_linux_amd64/
ExecStart=/opt/teamspeak3-server_linux_amd64/ts3server_startscript.sh start
ExecStop=/opt/teamspeak3-server_linux_amd64/ts3server_startscript.sh stop
PIDFile=/opt/teamspeak3-server_linux_amd64/ts3server.pid
Type=forking
RestartSec=15
Restart=always

[Install]
WantedBy=multi-user.target
</code></pre>
</li><li><p>重新加载 systemd</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">systemctl daemon-reload
</code></pre>
</li><li><p>开启服务自启动</p><pre class="language-shell lang-shell"><code class="language-shell lang-shell">systemctl enable teamspeak.service
</code></pre>
</li></ul><h3 id="">管理命令</h3><pre class="language-shell lang-shell"><code class="language-shell lang-shell">systemctl start teamspeak.service   # 启动 TeamSpeak
systemctl stop teamspeak.service    # 停止 TeamSpeak
systemctl restart teamspeak.service # 重启 TeamSpeak
</code></pre>
<h2 id="docker-compose--">Docker-Compose 一键部署 (推荐)</h2><pre class="language-yml lang-yml"><code class="language-yml lang-yml">version: &#x27;3.1&#x27;
services:
  teamspeak:
    image: teamspeak:3.13.7
    restart: always
    ports:
      - 9987:9987/udp
      - 10011:10011
      - 30033:30033
    volumes:
      - ./data:/var/ts3server
    environment:
      TS3SERVER_DB_USER: root
      TS3SERVER_DB_PASSWORD: password
      TS3SERVER_DB_NAME: teamspeak
      TS3SERVER_DB_WAITUNTILREADY: 30
      TS3SERVER_LICENSE: accept
</code></pre>
<h2 id="">客户端使用</h2><p>初次进入将会要求输入管理员密钥，即上文 <code>TOKEN</code></p><p><img src="https://s3.zcsouls.com/image/blog/20250306175707601.webp"/></p><p>随后即可获得管理员权限，在客户端管理 Teamspeak</p></div><p style="text-align:right"><a href="https://blog.zcsouls.com/posts/tech/ts3#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.zcsouls.com/posts/tech/ts3</link><guid isPermaLink="true">https://blog.zcsouls.com/posts/tech/ts3</guid><dc:creator><![CDATA[fl0w1nd]]></dc:creator><pubDate>Sun, 14 Aug 2022 09:24:28 GMT</pubDate></item></channel></rss>