一套成熟的团队软资产体系构建

目前随着团队成员增多,配置服务器及其相应的资产数量增多,其他组内事务也明显增多,之前基于微信等办公方式越来越麻烦,且管理难度耗费时间都明显变多,于是本指南意图说明团队各自资产的搭建及其管理方式,便于各个成员进行学习。

团队目前的在线服务包括JumpServer、Blog、Zerotier、Gitea、Drive、ToDo等,其服务主要部署在Ubuntu服务器上,采用1panel的可视化界面进行部署,采用Google Cloudflare进行DNS解析。

搭建

整个服务体系的搭建采用1Panel(安装教程)和Docker方式进行快速部署,并且方便迁移。

DNS解析及其反向代理

我们注册了一个ddwtop.team的域名作为团队的主域名,将1Panel的heimdall服务作为首页,将各个应用增加到主页上,便于访问。

image-20231205205731200

如果需要更改主页显示的内容,使用电脑打开ddwtop.team并且登录管理员账号便能完成更改。

image-20231205204512314

所有服务都是在内网服务器进行进行部署,为了实现所有服务的公网访问,必须使内网服务器能够连接到公网,所以我们对主要部署服务的服务器编写了Python脚本进行网络拨号,并设置了定时执行保证服务器一直能连上外网提供公网服务。

"""
@author yutanglee
@description 这个代码可以免浏览器拨号上网,原理很简单,就是给认证服务器发送一个http请求。
@use 你需要提供上网账号、密码和运营商,是否采用手机端或者PC端是可选的。手机端和PC端是指,重邮的每个上网账号可以同时存在一个PC账号和手机端。
"""
from ast import arg
from pydoc import describe
import requests
import subprocess
import re
import argparse
import base64


def login(usr, psw, isp, ip, mobile=True):
    
    url = 'http://192.168.200.2:801/eportal/?c=Portal&a=login&callback=dr1003&login_method=1&' +\
        'user_account=%2C0%2C' + usr + '%40' + isp +'&user_password=' + psw + '&wlan_user_ip=' + ip + \
        '&wlan_user_ipv6=&wlan_user_mac=000000000000&wlan_ac_ip=&wlan_ac_name=&jsVersion=3.3.3&v=10390'
    if not mobile:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.58'}
    else:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 Edg/114.0.1823.58'}
    r = requests.get(url=url, headers=headers)
    return r.text

def get_local_ip():
    try:
        # 运行 ip a 命令获取网络接口信息
        output = subprocess.check_output(["ip", "a"]).decode("utf-8")
        
        # 使用正则表达式解析 IP 地址
        ip_pattern = r"inet (\d+\.\d+\.\d+\.\d+)"
        match = re.findall(ip_pattern, output)
        
        # 筛选出以特定 IP 段开头的 IP 地址
        target_ips = [ip for ip in match if ip.startswith("10.16.") or ip.startswith("10.20.")]
        
        if target_ips:
            return target_ips[0]  # 返回第一个满足条件的 IP 地址
        else:
            return None
    except subprocess.CalledProcessError:
        return None

    
if __name__ == '__main__':
    args = argparse.ArgumentParser()
    args.add_argument('--user', type=str, default='统一认证码', help='your account for CQUPT network, maybe is your id number login ehall.cqupt.edu.cn')
    args.add_argument('--psw', type=str, default='密码', help='password')
    args.add_argument('--isp', type=str, default='xyw', help='cmcc|telecom|unicom|xyw')
    args.add_argument('--mobile', action='store_true', help='do you want use mobile mode?')
    args = args.parse_args()
    
    if args.isp != 'cmcc' and args.isp != 'telecom' and args.isp != 'unicom' and args.isp != 'xyw':
        print('运营商只支持cmcc|telecom|unicom|xyw  重新检查输入!')
        exit(1)

    ip = get_local_ip()
    if ip is None:
        ip = input("自动获取IP失败,请你输入正确的IP:")
    print('your ip is:', ip)
    print('your user is:', args.user)
    print('your password is:', args.psw)
    print('your isp is:', args.isp)
    args.mobile = True

    response = login(args.user, args.psw, args.isp, ip, args.mobile)
    start_index = response.find('"result":"') + len('"result":"')
    end_index = response.find('"', start_index)
    result_value = response[start_index:end_index]
    if result_value == '1':
        print('登录成功!')
    else:
        start_index = response.find('"msg":"') + len('"msg":"')
        end_index = response.find('"', start_index)
        msg_encoded = response[start_index:end_index]
        # 对msg进行Base64解码
        msg_decoded = base64.b64decode(msg_encoded).decode('utf-8')

        print(msg_decoded, response)
        if msg_decoded == 'ldap auth error':
            print('密码错误!')
        elif msg_decoded == 'userid error1':
            print('账号不存在!')
    

服务器有了访问公网IP的能力还不够,因为每次拨号上网之后公网IP可能进行改变,并且用来部署的服务器的内网IP是10字段,也是可能进行改变的。如果用传统的域名映射到单一IP的方式,再每次IP变化的时候就会失效,并且我们有多个服务,不能使用域名映射到单一域名。故我们采用Nignx的反向代理和ddns-go来解决上面的问题。

现阶段,每个电脑进行拨号之后虽然没有独一无二的IPv4地址,但是拥有独有的IPv6地址。我们在CLOUDFLARE中添加A记录ddns1907与服务器IPv4地址的映射,并且在AAAA记录添加ddns1907与服务器IPv6地址的映射,而其他记录作为CNAME,服务器名称与ddns1907.ddwtop.team的映射。使得所有服务在IPv4不可访问的情况下,在IPv6也一定能得到访问。具体配置如下图所示

image-20231205213021760

其具体的DNS映射操作过程,我们采用全自动的DDNS-GO工具可以实现通过CLOUDEFLARE的Token(Token设置)自动进行记录修改,我们只需配置DDNS-GO的相关信息。

image-20231205213516893

在Nignx的方向代理,我们采用可视化的1Panel进行操作。

image-20231205213914470

以jumpserver的服务举例,我们在配置信息的时候在主域名填写在DNS上配置的CNAME.ddwtop.team:80,在代理地址的地方输入服务部署的内网地址,如果是本服务器可以采用127.0.0.1或者localhost加上服务部署的端口。注明:因为zerotier需要一个不更改的IP所以部署地址在另一个服务器上,这里就需要填写另一台服务器的IP和端口。image-20231205214217105

DSM服务

团队目前有两个NAS系统,一个41T,一个 16T左右 , 还有200T左右的存储阵列,这部分主要介绍一下常用的NAS操作。我们使用的DSM服务器系统为Synology NAS,本质上也是一个LINUX系统。DSM有其可视化的网页界面,我们可以通过IP+端口的方式进行访问,对于这两台服务器,网页访问我们设置的端口为5000。因为DSM的服务器没有网口,要寻找DSM服务器的IP,我们采用的是使用群晖助手(下载链接)安装在笔记本上,然后通过网线连接到DSM接入的局域网中,启用群晖助手的搜索功能查找对应的DSM服务器IP,最后通过IP:5000能够进入系统界面。

在这个界面里面,我们能够看到团队用于存放团队个人文件的Synology Drive系统,可以对Drive进行可视化的管理。其更多的操作还是要参考官方文档

image-20231206130117543

另一个比较通用的便是桌面的Container Manager,这个功能是一个可视化的Docker 容器部署工具,前文提到的服务都能在其中看见,如果通过1Panel不能启动的Docker服务,在Container Manager可以进行启动,配置。在其中,我们能够看到所有的容器应用,并进行管理,如要开展新的应用比如MongoDB的部署,也能直接在其中进行启动,不必要采用传统的安装方式,简单高效。

由于图形化界面里面的功能不完善,比如Container Manager里面启动服务有时会出错,最好的方式还是通过SSH连接到DSM服务器中,通过命令行的方式进行服务器使用。对于如何开启DSM的SSH连接,我们只需要在控制面板中的终端机和SNMP一栏中开启SSH的功能就行,在连接的时候,还是使用进入系统页面的账号进入登录。

image-20231206131614839

DSM还有很多其他的功能,但需要自行探索,以上只说明了常用的3个使用场景,等待其他补充。