OpenWrt -- OpenVPN配置ServerClient(TUN模式)

news2024/11/19 1:21:47

一、前言

目标是两台设备能通过OpenVPN TUN模式建立连接。
准备如下:

  1. 设备

    友善R2S两台,一台做服务器,一台做客户端。
    一台小米R1C,当作网关。
  2. 固件

    采用openwrt-22.03版本,下载地址:https://downloads.openwrt.org/releases/22.03.5/targets/
    也可以根据实际情况自行编译。
  3. 网络拓扑

    小米R1C作为网关,用于配置端口转发。
    网关下挂OpenVPN Server端,即Server端WAN口连接网关LAN口。
    网关WAN口和Client端在同一网段,或者在不同网段,且保证Client端能够ping通服务端WAN口IP地址。
  4. 注意事项

    三台设备要重新刷机,保持系统为默认、干净状态。

二、安装相应组件包

Server端和Client端分别安装对应组件,执行以下命令:

opkg update
opkg install openvpn-openssl openvpn-easy-rsa luci-app-openvpn

三、证书及密钥生成

证书及密钥只需要在Server侧生成即可。

  1. easy-rsa目录处理
    目录处理,输入以下命令:

    KEY_DIR=/etc/config/openvpn_easy-rsa
    mkdir -p $KEY_DIR
    ll /etc/easy-rsa/*
    
    mv /etc/easy-rsa/* $KEY_DIR
    ln -s $KEY_DIR/* /etc/easy-rsa
    
    ll /etc/easy-rsa/*
    
  2. easy-rsa var变量设置

    /etc/easy-rsa/vars末尾添加以下内容并设置全局变量,直接执行以下命令:

    VARS="/etc/easy-rsa/vars"
    
    echo ""                                          >> $VARS
    echo "set_var EASYRSA_REQ_COUNTRY \"CN\""        >> $VARS
    echo "set_var EASYRSA_REQ_PROVINCE \"Beijing\""  >> $VARS
    echo "set_var EASYRSA_REQ_CITY \"Haidian\""      >> $VARS
    echo "set_var EASYRSA_REQ_ORG \"IT\""            >> $VARS
    echo "set_var EASYRSA_REQ_EMAIL \"IT\""          >> $VARS
    echo "set_var EASYRSA_REQ_OU \"IT\""             >> $VARS
    echo ""                                          >> $VARS
    echo "set_var EASYRSA_KEY_SIZE 2048"             >> $VARS
    
    cat $VARS
    
    source $VARS
    

    执行完 source $VARS后,会出现以下打印:

    root@OpenWrt:~# source $VARS
    You appear to be sourcing an Easy-RSA 'vars' file.
    This is no longer necessary and is disallowed. See the section called
    'How to use this file' near the top comments for more details.
    root@OpenWrt:~# 
    

    设置EasyRAS变量,输入以下命令:

    export EASYRSA_PKI="/etc/easy-rsa/pki"
    export EASYRSA_REQ_CN="ovpnca"
    export EASYRSA_BATCH="1"
    
  3. 初始化pki目录
    输入以下命令:

    cd /etc/easy-rsa
    easyrsa init-pki
    
  4. 生成Diffie-Hellman pem并打印
    输入以下命令:

    cd /etc/easy-rsa
    easyrsa gen-dh
    cat /etc/easy-rsa/pki/dh.pem
    

    此步骤耗时可能会比较长,请耐心等待。

  5. 生成ca证书及密钥并打印
    输入以下命令:

    cd /etc/easy-rsa
    easyrsa build-ca nopass
    cat /etc/easy-rsa/pki/ca.crt
    
  6. 生成Server证书及密钥并打印
    输入以下命令:

    cd /etc/easy-rsa
    easyrsa build-server-full server nopass
    cat /etc/easy-rsa/pki/private/server.key
    
  7. 生成Client证书及密钥并打印

    输入以下命令:

    cd /etc/easy-rsa
    easyrsa build-client-full client nopass
    cat /etc/easy-rsa/pki/private/client.key
    
  8. 生成tls密钥并打印

    输入以下命令:

    cd /etc/easy-rsa
    openvpn --genkey --secret ${EASYRSA_PKI}/tc.pem
    cat /etc/easy-rsa/pki/tc.pem
    

四、OpenVPN Server配置

以下操作都在第一台R2S路由器上面执行,我们称这台路由器为Server端。

  1. Server防火墙默认配置修改

    规则全部改为ACCEPT,输入以下命令查看防火墙当前默认配置:

    uci show firewall | grep defaults 
    

    会有如下打印:

    firewall.@defaults[0]=defaults
    firewall.@defaults[0].syn_flood='1'
    firewall.@defaults[0].input='ACCEPT'
    firewall.@defaults[0].output='ACCEPT'
    firewall.@defaults[0].forward='REJECT'  
    

    我们需要将firewall.@defaults[0].forward='REJECT'改为firewall.@defaults[0].forward='ACCEPT'

    输入以下命令:

    uci set firewall.@defaults[0].forward='ACCEPT'  
    

    同理修改LAN口和WAN口的配置,输入以下命令查看防火墙当前默认配置:

    uci show firewall | grep zone  
    

    会有如下打印:

    firewall.@zone[0]=zone
    firewall.@zone[0].name='lan'
    firewall.@zone[0].network='lan'
    firewall.@zone[0].input='ACCEPT'
    firewall.@zone[0].output='ACCEPT'
    firewall.@zone[0].forward='ACCEPT'
    firewall.@zone[1]=zone
    firewall.@zone[1].name='wan'
    firewall.@zone[1].network='wan' 'wan6'
    firewall.@zone[1].input='REJECT'
    firewall.@zone[1].output='ACCEPT'
    firewall.@zone[1].forward='REJECT'
    firewall.@zone[1].masq='1'
    firewall.@zone[1].mtu_fix='1' 
    

    firewall.@zone[1].input='REJECT'改为firewall.@zone[1].input='ACCEPT'

    firewall.@zone[1].forward='REJECT'改为firewall.@zone[1].forward='ACCEPT'

    输入以下命令:

    uci set firewall.@zone[1].input='ACCEPT'
    uci set firewall.@zone[1].forward='ACCEPT'
    

    执行以下命令更新防火墙配置:

    uci commit firewall /etc/init.d/firewall restart  
    
  2. VPN端口协议及防火墙配置

    定义VPN服务端传输协议及端口,输入以下命令:

    OVPN_PORT="11194"
    OVPN_PROTO="udp"
    

    防火墙内添加tun+设备接口,输入以下命令:

    uci rename firewall.@zone[0]="lan"
    uci rename firewall.@zone[1]="wan"
    uci del_list firewall.lan.device="tun+"
    uci add_list firewall.lan.device="tun+"
    uci -q delete firewall.ovpn
    

    根据传输协议及端口对防火墙进行配置,执行以下命令:

    uci set firewall.ovpn="rule"
    uci set firewall.ovpn.name="Allow-OpenVPN"
    uci set firewall.ovpn.src="wan"
    uci set firewall.ovpn.dest_port="${OVPN_PORT}"
    uci set firewall.ovpn.proto="${OVPN_PROTO}"
    uci set firewall.ovpn.target="ACCEPT"
    

    更新防火墙配置并查看配置参数,执行以下命令

    uci commit firewall
    /etc/init.d/firewall restart
    
    uci show firewall.ovpn
    cat /proc/sys/net/ipv4/ip_forward
    
  3. 接口创建及信息完善
    创建一个名为ovpn_server的vpn接口,输入以下命令:

    export EASYRSA_PKI="/etc/easy-rsa/pki"
    
    uci set openvpn.ovpn_server="openvpn"
    uci set openvpn.ovpn_server.enabled="1"
    uci set openvpn.ovpn_server.dev="tun"
    uci set openvpn.ovpn_server.port="11194"
    uci set openvpn.ovpn_server.proto="udp"
    uci set openvpn.ovpn_server.comp_lzo="no"
    uci set openvpn.ovpn_server.log="/tmp/openvpn.log"
    uci set openvpn.ovpn_server.status="/tmp/openvpn.status"
    uci set openvpn.ovpn_server.verb="3"
    uci set openvpn.ovpn_server.mute="5"
    uci set openvpn.ovpn_server.keepalive="10 60"
    uci set openvpn.ovpn_server.persist_key="1"
    uci set openvpn.ovpn_server.persist_tun="1"
    uci set openvpn.ovpn_server.user="nobody"
    uci set openvpn.ovpn_server.group="nogroup"
    uci set openvpn.ovpn_server.ca="${EASYRSA_PKI}/ca.crt"
    uci set openvpn.ovpn_server.cert="${EASYRSA_PKI}/issued/server.crt"
    uci set openvpn.ovpn_server.dh="${EASYRSA_PKI}/dh.pem"
    uci set openvpn.ovpn_server.key="${EASYRSA_PKI}/private/server.key"
    uci set openvpn.ovpn_server.mode="server"
    uci set openvpn.ovpn_server.server="192.168.0.0 255.255.255.0"
    uci set openvpn.ovpn_server.tls_server="1"
    uci set openvpn.ovpn_server.topology="subnet"
    uci set openvpn.ovpn_server.route_gateway="dhcp"
    uci set openvpn.ovpn_server.client_to_client="1"
    uci commit openvpn
    
    uci add_list openvpn.ovpn_server.push="comp-lzo no"
    uci add_list openvpn.ovpn_server.push="persist-key"
    uci add_list openvpn.ovpn_server.push="persist-tun"
    uci add_list openvpn.ovpn_server.push="user nobody"
    uci add_list openvpn.ovpn_server.push="user nogroup"
    uci add_list openvpn.ovpn_server.push="topology subnet"
    uci add_list openvpn.ovpn_server.push="route-gateway dhcp"
    uci add_list openvpn.ovpn_server.push="redirect-gateway def1"
    uci add_list openvpn.ovpn_server.push="192.168.0.0 255.255.255.0"
    uci add_list openvpn.ovpn_server.push="dhcp-option DNS 9.9.9.9"
    uci add_list openvpn.ovpn_server.push="dhcp-option DNS 1.1.1.1"
    uci commit openvpn
    
  4. VPN服务使能
    查看ovpn_server和防火墙配置,输入以下命令:

    uci show openvpn.ovpn_server
    uci show firewall.ovpn
    

    使能ovpn_server服务器以及启动此服务,输入以下命令:

    /etc/init.d/openvpn enable
    /etc/init.d/openvpn start
    
  5. Server侧状态及log确认
    查看ovpn_server启动状态,输入以下命令:

    pgrep -f -a openvpn
    

    有类似以下打印说明服务已启动:

    root@OpenWrt:/# pgrep -f -a openvpn
    2812 /usr/sbin/openvpn --syslog openvpn(ovpn_server) --status /var/run/openvpn.ovpn_server.status --cd /var/etc --config openvpn-ovpn_server.conf --up /usr/libexec/openvpn-hotplug up ovpn_server --down /usr/libexec/openvpn-hotplug down ovpn_server --script-security 2
    root@OpenWrt:/# 
    

    查看Server vpn log及状态log,输入以下命令:

    cat /tmp/openvpn.log 
    cat /tmp/openvpn.status
    

    有类似以下打印说明成功:

    root@OpenWrt:/# 
    root@OpenWrt:/# cat /tmp/openvpn.log 
    2023-08-08 01:57:40 --cipher is not set. Previous OpenVPN version defaulted to BF-CBC as fallback when cipher negotiation failed in this case. If you need this fallback please add '--data-ciphers-fallback BF-CBC' to your configuration and/or add BF-CBC to --data-ciphers.
    2023-08-08 01:57:40 OpenVPN 2.5.7 aarch64-openwrt-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD]
    2023-08-08 01:57:40 library versions: OpenSSL 1.1.1u  30 May 2023, LZO 2.10
    2023-08-08 01:57:40 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
    2023-08-08 01:57:40 Diffie-Hellman initialized with 2048 bit key
    2023-08-08 01:57:40 TUN/TAP device tun0 opened
    2023-08-08 01:57:40 /sbin/ip link set dev tun0 up mtu 1500
    2023-08-08 01:57:40 /sbin/ip link set dev tun0 up
    2023-08-08 01:57:40 /sbin/ip addr add dev tun0 192.168.0.1/24
    2023-08-08 01:57:40 /usr/libexec/openvpn-hotplug up ovpn_server tun0 1500 1622 192.168.0.1 255.255.255.0 init
    2023-08-08 01:57:40 Could not determine IPv4/IPv6 protocol. Using AF_INET
    2023-08-08 01:57:40 Socket Buffers: R=[212992->212992] S=[212992->212992]
    2023-08-08 01:57:40 UDPv4 link local (bound): [AF_INET][undef]:1193
    2023-08-08 01:57:40 UDPv4 link remote: [AF_UNSPEC]
    2023-08-08 01:57:40 GID set to nogroup
    2023-08-08 01:57:40 UID set to nobody
    2023-08-08 01:57:40 MULTI: multi_init called, r=256 v=256
    2023-08-08 01:57:40 IFCONFIG POOL IPv4: base=192.168.0.2 size=253
    2023-08-08 01:57:40 Initialization Sequence Completed
    root@OpenWrt:/# 
    root@OpenWrt:/# cat /tmp/openvpn.status 
    OpenVPN CLIENT LIST
    Updated,2023-08-08 02:00:42
    Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
    ROUTING TABLE
    Virtual Address,Common Name,Real Address,Last Ref
    GLOBAL STATS
    Max bcast/mcast queue length,0
    END
    root@OpenWrt:/# 
    root@OpenWrt:/# 
    

    执行ifconfig命令后,能够看到显示的信息中有tun0接口,如下:

    tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
              inet addr:192.168.0.1  P-t-P:192.168.0.1  Mask:255.255.255.0
              inet6 addr: fe80::5c0:4e74:d46b:8601/64 Scope:Link
              UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:500 
              RX bytes:0 (0.0 B)  TX bytes:304 (304.0 B)
    
  6. LAN侧默认网关修改
    由于OpenWrt LAN侧默认网关为192.168.1.1,通过Luci界面将其修改为其它网段,这儿修改为192.168.12.1
    修改原因是OpenVPN建立隧道后,在每个私有网络中,确保私有网络内的主机具有对方私有网络的IP地址和子网掩码,以便它们可以相互通信。

五、OpenVPN Client配置

以下操作都在第二台R2S路由器上面执行,我们称这台路由器为Client端。

  1. 配置文件设置
    创建/root/vpn并且在此文件夹下创建client.conf文件,输入以下命令:
    mkdir -p /root/vpn
    vi /root/vpn/client.conf
    
    client.conf里面输入以下信息:
    auth-nocache                                                    
    client                                                          
    comp-lzo no                                                     
    dev tun                                                         
    mute 10                                                         
    nobind                                                          
                                                                    
    persist-key                                                     
    persist-tun                                                     
                                                                    
    proto udp                                                       
    remote 192.168.2.200 11194                                      
                                                                    
    remote-cert-tls server                                          
    resolv-retry infinite                                           
    script-security 1                                               
                                                                    
    verb 3                  
    log-append /tmp/openvpn.log
    status /tmp/openvpn.status
    
    <key>
    # Insert here the client's generated private key from:
    # cat /etc/easy-rsa/pki/private/client.key
    </key>
    <cert>
    # Insert here the client's generated certificate from:
    # cat /etc/easy-rsa/pki/issued/client.crt
    </cert>
    <ca>
    # Place here the server's generated certificate from:
    # cat /etc/easy-rsa/pki/ca.crt
    </ca>
    
    其中,remote 192.168.2.200 11194192.168.2.200表示网关的IP地址,即网关WAN口地址。将Server生成的证书密钥按照要求填写到配置文件最后的key/cert/ca中。
  2. Client防火墙默认配置修改
    Client侧的修改方式同Server侧一样,输入以下命令即可:
    uci set firewall.@defaults[0].forward='ACCEPT'
    uci set firewall.@zone[1].input='ACCEPT'
    uci set firewall.@zone[1].forward='ACCEPT'
    
    执行以下命令更新防火墙配置:
    uci commit firewall
    /etc/init.d/firewall restart
    
  3. 配置文件修改及服务使能
    打开openvpn配置文件,输入以下命令:
    vi /etc/config/openvpn
    
    修改config openvpn custom_config里面的配置:
    option enabled 0改为option enabled 1
    option config /etc/openvpn/my-vpn.conf改为option config /etc/openvpn/my-vpn.conf
    修改后的配置文件如下:
    package openvpn
    
    #################################################
    # Sample to include a custom config file.       #
    #################################################
    
    config openvpn custom_config
    
            # Set to 1 to enable this instance:
            option enabled 1
    
            # Credentials to login
            #option username 'login'
            #option password 'password'
    
            # Password for client certificate
            #option cert_password 'cert_password'
    
            # Include OpenVPN configuration
            option config /root/vpn/client.conf   
    
    输入以下命令启动客户端vpn服务:
    /etc/init.d/openvpn enable
    /etc/init.d/openvpn start
    
  4. Client侧状态及log确认
    同Server侧一样,查看方式为:
    pgrep -f -a openvpn
    cat /tmp/openvpn.log 
    cat /tmp/openvpn.status
    

六、网关配置

  1. 网络拓扑
    小米R1C网关WAN侧地址192.168.2.200
    小米R1C网关LAN侧地址192.168.50.1
    友善R2S Server侧WAN口接小米R1C网关LAN口,R2S Server WAN口地址为192.168.50.201
    友善R2S Client侧WAN口和小米R1C网关WAN口为同一网段,R2S Client WAN口地址为192.168.2.116

  2. 网关防火墙配置
    浏览器输入192.168.50.1登录网关,选择【网络】->【防火墙】打开防火墙配置,如下图:
    在这里插入图片描述
    防火墙具体配置见下图画红框的部分:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2v3JYLm5-1692177001052)(C:\Users\xuyanbin\AppData\Roaming\Typora\typora-user-images\image-20230816170351323.png)]
    注意上图中【WAN => 】侧的编辑里面的一个配置项【MSS clamping】也要勾选,配置完后检测网关的防火墙设置是否和上图一样,如果一样,点击【保存并应用】。

  3. 网关端口转发配置

    在上一步骤网关防火墙配置的基础上,点击选择【网络】->【防火墙】->【Port Forwards】-> 【添加】配置端口转发,如下图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KkWFuByr-1692177001054)(C:\Users\xuyanbin\AppData\Roaming\Typora\typora-user-images\image-20230816170426335.png)]
    弹出配置界面,按以下配置:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YHqMeRUr-1692177001054)(C:\Users\xuyanbin\AppData\Roaming\Typora\typora-user-images\image-20230816170434820.png)]

    说明:
    名称填写vpn_tun
    External port填写外部端口即Client侧的端口11194
    Internal adress填写内部Server WAN侧的IP地址,192.168.50.201
    Internal port填写内部Server侧的端口11194
    配置完成后点击【保存】返回到上一层页面,确认配置无误后,点击【保存并应用】,如下图:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-riM9ZiKU-1692177001055)(C:\Users\xuyanbin\AppData\Roaming\Typora\typora-user-images\image-20230816170524798.png)]

七、测试

先重启服务端再重启客户端。
Client侧输入ifconfig tun0,如果tun0有IP显示,则说明VPN隧道建立成功,如下所示:

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:192.168.0.2  P-t-P:192.168.0.2  Mask:255.255.255.0
          inet6 addr: fe80::762a:9b34:4ee9:edb7/64 Scope:Link
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2631 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:0 (0.0 B)  TX bytes:176649 (172.5 KiB)

如果关闭网关的端口转发或者关掉Server侧的OpenVPN服务,Client侧执行ifconfig命令则不会有tun0设备。

八、参考

https://github.com/OpenVPN/openvpn/
https://openwrt.org/docs/guide-user/services/vpn/openvpn/start

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/886483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EmbedPress Pro 在WordPress网站中嵌入任何内容

EmbedPress Pro可让您通过高级自定义、自定义品牌、延迟加载和更多惊人功能嵌入源。为古腾堡块和Elementor编辑器提供支持的一体化 WordPress 嵌入解决方案。使用 EmbedPress 在古腾堡创建交互式内容。使用 EmbedPress 的古腾堡块立即将任何内容嵌入到您的网站。 网址: EmbedP…

合成数据及其在AI领域中的作用

什么是合成数据&#xff1f; 合成数据是由人工创建而非从现实生活中获得的数据&#xff0c;它从机器学习对数据的需求发展而来。最初&#xff0c;为了精确训练AI模型&#xff0c;必须获得涵盖所有可能场景的训练数据。如果某个场景没有发生或未被获得&#xff0c;就没有相应的…

23.8.16日总结

原先写的评论是每级评论用缩进来区分&#xff0c;所以最多设置的是九级评论&#xff0c;修改了排版和格式&#xff1a; 还有管理员页面&#xff0c;查看文章时可以进行点赞&#xff0c;收藏的操作&#xff0c;现在进行了修改&#xff0c;将相关操作隐藏。 还有点击查看未发布…

UE4/UE5 照明构建失败 “Lightmass crashed”解决“数组索引越界”

在构建全局光照时,经常会出现“Lightmass crashed”的错误,导致光照构建失败。本文将分析这一问题的原因,并给出解决建议。 UE4 版本4.26 报错如下: <None> === Lightmass crashed: === Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:d:\build…

Android Studio 新建module报错:No signature of method

android平台uni原生插件开发过程中&#xff0c;使用Android Studio 新增 module 报错 选择app --> create new module &#xff0c;填写相关信息 Android Studio 新建module报错&#xff1a; 原因&#xff1a;Android Studio 版本过高&#xff0c;新增了namespace&#x…

Redis——hash类型详解

概述 Redis本身就是键值对结构&#xff0c;而Redis中的value可以是哈希类型&#xff0c;为了区分这两个键值对&#xff0c;Redis中的键值对是key-value&#xff0c;而value中的哈希键值对则是field-value&#xff0c;其中value必须是字符串 下面介绍一些Redis的hash类型的常用…

数据可视化和数字孪生相互促进的关系

数据可视化和数字孪生是当今数字化时代中备受关注的两大领域&#xff0c;它们在不同层面和领域为我们提供了深入洞察和智能决策的机会&#xff0c;随着两种技术的不断融合发展&#xff0c;很多人会将他们联系在一起&#xff0c;本文就带大家浅谈一下二者之间相爱相杀的关系。 …

软件工程模型-架构师之路(四)

软件工程模型 敏捷开发&#xff1a; 个体和交互 胜过 过程和工具、可以工作的软件 胜过 面面俱到的文件、客户合作胜过合同谈判、响应变化 胜过 循序计划。&#xff08;适应需求变化&#xff0c;积极响应&#xff09; 敏捷开发与其他结构化方法区别特点&#xff1a;面向人的…

chromedriver、geckodriver、MicrosoftWebDriver、IEDriverServer和operadriver之间的恩怨纠葛

测试环境&#xff1a;操作系统为Windows10-64位 具体目标&#xff1a;安装五大浏览器及其驱动 目录 一、谷歌浏览器1.Google Chrome的安装2.chromedriver的下载 二、火狐浏览器1.Firefox的安装2.geckodriver的下载 三、Edge浏览器1.Microsoft Edge的安装2.MicrosoftWebDriver的…

563.二叉树的坡度(递归)

一、题目 563. 二叉树的坡度 - 力扣&#xff08;LeetCode&#xff09; 二、代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* …

Spring的简介ioc容器及注入方式

一.Spring的简介 1.Spring的特性 Spring是一个开源框架&#xff0c;它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。 Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。 然而&#xff0c;Spring的用途不仅限于服务器端的开发。从简单性、可测试性…

Shell编程——弱数据类型的脚本语言快速入门指南

目录 Linux Shell 数据类型 变量类型 运算符 算术运算符 赋值运算符 拼接运算符 比较运算符 关系运算符 控制结构 顺序结构 条件分支结构 if 条件语句 case 分支语句 循环结构 for 循环 while 循环 until 循环 break 语句 continue语句 函数 函数定义 …

Matplotlib绘图知识小结--Python数据分析学习

一、Pyplot子库绘制2D图表 1、Matplotlib Pyplot Pyplot 是 Matplotlib 的子库&#xff0c;提供了和 MATLAB 类似的绘图 API。 Pyplot 是常用的绘图模块&#xff0c;能很方便让用户绘制 2D 图表。 Pyplot 包含一系列绘图函数的相关函数&#xff0c;每个函数会对当前的图像进行…

线上问题排查: jmap mat 工具排查生产环境占用内存过大问题

一. 背景 线上任务内存占用居高不下, 机器load较高. 排查问题原因. 二. 操作 2.1. 工具文件下载清单. mat 工具 linux版本. ( dump文件太大了有20多G, 只能在服务器上解析. 所以下载linux版本. ) 下载地址: https://eclipse.dev/mat/downloads.php 下载高版本的jdk , 目前…

Spark第二课RDD的详解

1.前言 RDD JAVA中的IO 1.小知识点穿插 1. 装饰者设计模式 装饰者设计模式:本身功能不变,扩展功能. 举例&#xff1a; 数据流的读取 一层一层的包装&#xff0c;进而将功能进行进一步的扩展 2.sleep和wait的区别 本质区别是字体不一样,sleep斜体,wait正常 斜体是静态方法…

数学 容斥原理

全都是mn-1&#xff0c;下图都写成m-n-1了&#xff0c;没有脑子o(╥﹏╥)o 题目链接&#xff1a;214. Devu和鲜花 - AcWing题库 #include <bits/stdc.h> #define ll long long using namespace std; const int mod 1e97; ll A[25]; ll Pow(ll a, ll k){ll ans 1;while…

538页21万字数字政府智慧政务大数据云平台项目建设方案WORD

导读&#xff1a;原文《538页21万字数字政府智慧政务大数据云平台项目建设方案WORD》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 根据业务的不同属性&#xff0c…

爱校对:公文材料的新时代伙伴

在这个数字化、智能化日益增强的新时代&#xff0c;公文材料处理方式也在发生着巨大的变化。传统的人工校对方式逐渐被智能化的工具所替代&#xff0c;而在这其中&#xff0c;爱校对正以其卓越的性能和便捷的使用体验&#xff0c;崭露头角&#xff0c;成为公文材料处理的新时代…

利用高级定时器产生PWM

这个图中阐述了利用高级定时器产生PWM的原理&#xff0c;其中 ARR是自动重装载寄存器(TIMx_ARR)的值 CNT是定时器计数器当前的值 CCRx是捕获/比较寄存器 x(TIMx_CCRx)的值 每经过一次定时器时钟周期就会1&#xff0c;通过设置定时器的输出模式&#xff0c;可以实现&#xff0c…

编译工具:CMake(四)|安装目标文件、普通文件、脚本、目录

编译工具&#xff1a;CMake&#xff08;四&#xff09;|安装目标文件、普通文件、脚本、目录 如何安装目标文件的安装普通文件的安装&#xff1a;非目标文件的可执行程序安装(比如脚本之类)目录的安装 如何安装 安装的需要有两种&#xff0c;一种是从代码编译后直接 make inst…