n2n 2.8 虚拟局域网搭建 | n2n build with x64 | GTFO n2n

标签: none

n2n 是一个开放源代码的第2层轻量VPN程序,该程序利用了点对点的架构来处理网络间的成员关系和路由。

先决条件 2020-12 更新

由于我们需要自己自建整个 n2n ,因此我们需要一台有公网固定 IP 地址的服务器来充当 supernode 的角色
vps: aliyun-ecs.t5-lc2m1.nano 1核512MB Centos 7 宽带25Mbps

注意: 472a987 2.8 版本使用压缩存在内存泄漏, 在 99e56e9 得到修复.

构建环境
Windows 10
Visual Studio 2017 安装 Desktop development with C++ 开发套件
OpenSSL-1.1.1i 编译指南
zstd-1.4.8.tar.gz - Zstandard v1.4.8
cmake-3.12.4-win64-x64.msi
n2n-2.8 Stable Release
OpenVPN-2.5.0-I601-amd64.msi (TAP 网卡驱动 TAP-Windows Provider V9 - 9.24.6.601)

编译好的版本已修复内存泄漏 不想努力下载这个
n2n-2.8.r540.53afd3c-x64-with-openssl-1.1.1-zstd-1.4.8-Release-AceSheep.zip

开始

Windows 10 客户端

首先准备好Cmake, Openssl, zstd
n2n-2.8 在 windows 上支持 zstd 很复杂 需要修改 CMakeLists.txt, 大概这几个内容
删除代码里所有 #ifdef HAVE_LIBZSTD ... #endif 项目太乱了

add_definitions(-DHAVE_OPENSSL_1_1)
add_definitions(-DN2N_HAVE_AES)
add_definitions(-DN2N_HAVE_ZSTD)
add_definitions(-DHAVE_LIBZSTD)
target_link_libraries(n2n "C:/zstd-1.4.8/build/VS2010/bin/x64_Release/libzstd_static.lib")

zstd-1.4.8 不要下载编译好的我们要自己编译, 不然静态 zstd 会不够静态 (大雾
下载解压之后在 zstd-1.4.8\build\VS2010\zstd.sln 中 编译 libzstd 就可以使用了
zstd-1.4.8\build\VS2010\bin\x64_Release\libzstd_static.lib

解压源码 e:\n2n-2.8, 新建一个 buildbuild64 文件夹

在 build 文件里打开cmd窗口
x86 -A Win32
x64 -A x64

C:\n2n-2.8\build64>cmake .. -A x64 -DOPENSSL_ROOT_DIR=C:\openssl-1.1.1i\build64 -DOPENSSL_USE_STATIC_LIBS=true

这时候我们会遇到第一个错误

n2n.h(42,10): fatal error C1083: 无法打开包括文件: “config.h”: No such file or directory

Snipaste_2020-12-20_16-38-05.png

--- a/include/n2n.h
+++ b/include/n2n.h
@@ -38,11 +38,7 @@
 #ifdef WIN32
 #include "win32/n2n_win32.h"

-#ifdef _MSC_VER
-#include "config.h" /* Visual C++ */
-#else
 #include "win32/winconfig.h"
-#endif
 #define N2N_CAN_NAME_IFACE 1
 #undef N2N_HAVE_DAEMON
 #undef N2N_HAVE_SETUID

按照上面说的修改下 n2n.h 重新编译。

C:\n2n-2.8\build64>cmake .. -A x64 -DOPENSSL_ROOT_DIR=C:\openssl-1.1.1i\build64 -DOPENSSL_USE_STATIC_LIBS=true
-- Building for: Visual Studio 15 2017
-- The C compiler identification is MSVC 19.16.27045.0
-- The CXX compiler identification is MSVC 19.16.27045.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
fatal: Not a git repository (or any of the parent directories): .git
fatal: Not a git repository (or any of the parent directories): .git
-- Build from git rev: 2.7.0.r.AceSheep
-- Configuring done
-- Generating done
-- Build files have been written to: C:/n2n-2.8/build64

执行完在目录下会生成 n2n.sln 解决方案, 在 ALL_BUILD 右键选择 Build 就可以了

这时候属于我们的edge就出炉了

edge.exe -h
Welcome to n2n v.2.7.0.r.AceSheep for Windows-10.0.15063
Built on Dec 18 2020 20:27:33
Copyright 2007-2020 - ntop.org and contributors

edge  (see edge.conf)
or
edge -d  -a [static:|dhcp:] -c  [-k ]
    [-s ] [-n cidr:gateway] [-m ] -l 
    [-p ] [-M ] [-D] [-r] [-E] [-v] [-i ] [-L ] [-t ] [-A[]] [-H] [-z[]] [-h]

-d           | tun device name
-a         | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'
-c            | n2n community name the edge belongs to.
-k          | Encryption key (ASCII) - also N2N_KEY=.
-s              | Edge interface netmask in dotted decimal notation (255.255.255.0).
-l  | Supernode IP:port
-i         | Registration interval, for NAT hole punching (default 20 seconds)
-L              | TTL for registration packet when UDP NAT hole punching through supernode (default 0 for not set )
-p           | Fixed local UDP port.
-m          | Fix MAC address for the TAP interface (otherwise it may be random)
                         | eg. -m 01:02:03:04:05:06
-M                  | Specify n2n MTU of edge interface (default 1290).
-D                       | Enable PMTU discovery. PMTU discovery can reduce fragmentation but
                         | causes connections stall when not properly supported.
-r                       | Enable packet forwarding through n2n community.
-A1                      | Disable payload encryption. Do not use with key (defaulting to Twofish then).
-A2 ... -A5 or -A        | Choose a cipher for payload encryption, requires a key: -A2 = Twofish (default),
                         | -A3 or -A (deprecated) = AES-CBC, -A5 = Speck-CTR.
-H                       | Enable full header encryption. Requires supernode with fixed community.
-z1 ... -z2 or -z        | Enable compression for outgoing data packets: -z1 or -z = lzo1x (default=disabled).
-E                       | Accept multicast MAC addresses (default=drop).
-S                       | Do not connect P2P. Always use the supernode.
-n         | Route an IPv4 network via the gw. Use 0.0.0.0/0 for the default gw. Can be set multiple times.
-v                       | Make more verbose. Repeat as required.
-t                 | Management UDP Port (for multiple edges on a machine).

Environment variables:
  N2N_KEY                | Encryption key (ASCII). Not with -k.

Available TAP adapters:
  {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} - OpenVPN TAP-Windows6

Windows 10:
需要安装TAP 网卡驱动 TAP-Windows Provider V9 - 9.24.6.601
OpenVPN-2.5.0-I601-amd64.msi
这个驱动是OpenVPN里面的, 下载好社区版的msi文件之后可以使用命令仅安装TAP 驱动

在下载的文件夹打开命令行执行, 这样可以不用在GUI里面选择需要安装的项目.
重命名网卡, 设置为 OpenVPN TAP-Windows6

msiexec /i OpenVPN-2.5.0-I601-amd64.msi ADDLOCAL=Drivers.TAPWindows6 /passive
ncpa.cpl

once-install.bat

@echo off
chcp 936
cls
%1 %2
mode con:cols=46 lines=5
net session >nul 2>&1
if not %errorlevel% equ 0 (
    echo 错误 - 脚本必须以管理员身份运行或者女装!
    echo:
    echo 在弹出窗口点击 '允许'
) else ( goto :begin )

mshta vbscript:createobject("shell.application").shellexecute("%~dp0%~snx0","goto :begin","","runas",1)(window.close)&&exit

:begin
echo.
echo 正在安装 TAP Windows 虚拟网卡
cd "%~dp0"
msiexec /i OpenVPN-2.5.0-I601-amd64.msi ADDLOCAL=Drivers.TAPWindows6 /passive
echo.
echo 启动控制面板网络适配器设置 修改虚拟网卡名称为  OpenVPN TAP-Windows6
::ncpa.cpl
netsh interface show interface
echo.
echo 正在设置防火墙
PowerShell -Command "& {Set-NetFirewallRule -Name FPS-ICMP4-ERQ-In -Enabled True}"
PowerShell -Command "& {Get-NetFirewallRule -Name FPS-ICMP4-ERQ-In}"

echo.
echo 已经安装完成, 可以启动试试了.
ping 127.0.0.1 -n 6 -w 1000 2>nul 1>nul
exit

其他的用法

/i           - the installer file
/passive     - run as silent
ADDLOCAL=    - choose what to install, including:
             - OpenVPN.Service
             - OpenVPN
             - OpenVPN.GUI
             - OpenVPN.GUI.OnLogon
             - Drivers
             - Drivers.Wintun
             - Drivers.TAPWindows6
PRODUCTDIR=  - target directory

e.g.:
msiexec /i OpenVPN-2.5.msi ADDLOCAL=OpenVPN.Service,OpenVPN,Drivers,Drivers.Wintun /passive

运行

第一次启动需要使用管理员身份运行, 不然无法设置ip地址
password: Cartoons - Witch Doctor

edge.exe -l 1xx.1xx.1xx.1xx:6666 -d "OpenVPN TAP-Windows6" -c GTFO -A3 -k 51522zzwlwlbb -a 192.168.6.100

20/Dec/2020 00:00:14 [edge_utils.c:2575] Adding supernode[0] = 1xx.1xx.1xx.1xx:6666
20/Dec/2020 00:00:14 [edge.c:852] Starting n2n edge 2.7.0.r.AceSheep Dec 20 2020 13:42:56
20/Dec/2020 00:00:14 [edge.c:858] Using compression: none.
20/Dec/2020 00:00:14 [edge.c:859] Using AES-CBC cipher.
20/Dec/2020 00:00:14 [edge.c:869] ip_mode='static'
Open device [name={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}][ip=192.168.6.100][ifName=OpenVPN TAP-Windows6][MTU=1290][mac=01:02:03:04:05:06]
20/Dec/2020 00:00:14 [edge_utils.c:211] supernode 0 => 1xx.1xx.1xx.1xx:6666
20/Dec/2020 00:00:14 [edge.c:947] edge started
20/Dec/2020 00:00:24 [edge_utils.c:1800] [OK] Edge Peer <<< ================ >>> Super Node

也可以设置配置文件 edge.conf

-c=GTFO
-A3
-k=51522zzwlwlbb

# 服务器地址
-l=1xx.1xx.1xx.1xx:6666
# openVPN 网卡名称
-d=OpenVPN TAP-Windows6

# edge IP address 修改这里  2-254  192.168.6.xxx
-a=192.168.6.100

ping 不通 / ping 超时

需要开启防火墙规则, 管理员 cmd 执行

CMD witn Administrator 有的系统运行不成功优先使用 PowerShell 命令:
netsh advfirewall firewall set rule name="File and Printer Sharing (Echo Request - ICMPv4-In)" dir=in new enable=Yes

PowerShell witn Administrator:
Set-NetFirewallRule -Name FPS-ICMP4-ERQ-In -Enabled True

设置网卡跃点数 / 优先级

管理员 cmd 执行

>netsh interface ipv4 show interfaces
Idx     Met         MTU          State                Name
---  ----------  ----------  ------------  ---------------------------
  1          75  4294967295  connected     Loopback Pseudo-Interface 1
  9          10        1290  connected     OpenVPN TAP-Windows6
 23          35        1500  connected     VMware Network Adapter VMnet1
 28          35        1500  connected     VMware Network Adapter VMnet8
 10          25        1500  connected     Ethernet 7

找到TAP 网卡 Idx 为 9

>netsh interface ipv4 set interface 9 metric=10
Ok.

这样就成功了

隐藏黑色的运行窗口

新建一个 start.bat 文件, 保存运行就可以了. 结束的时候运行stop.bat taskkill /f /im edge.exe

目录结构

Snipaste_2021-03-28_12-36-58.png

start.bat

@echo off
chcp 936
cls
%1 %2
mode con:cols=46 lines=5
net session >nul 2>&1
if not %errorlevel% equ 0 (
    echo 错误 - 脚本必须以管理员身份运行或者女装!
    echo:
    echo 在弹出窗口点击 '允许'
) else ( goto :begin )

::mshta vbscript:createobject("wscript.shell").run("%~dp0%~nx0 h",0)(window.close)&&exit
mshta vbscript:createobject("shell.application").shellexecute("%~dp0%~snx0","goto :begin","","runas",0)(window.close)&&exit

:begin
tasklist /nh|find /i "n2nedge.exe"
if ERRORLEVEL 1 (
    "%~dp0n2nedge.exe" "%~dp0edge.conf"
    exit
) else (
    echo n2nedge.exe is already running
    exit
)

stop.bat

@echo off
chcp 936
cls
mode con:cols=46 lines=5
%1 %2

net session >nul 2>&1
if not %errorlevel% equ 0 (
    echo 错误 - 脚本必须以管理员身份运行或者女装!
    echo:
    echo 在弹出窗口点击 '允许'
) else ( goto :begin )

mshta vbscript:createobject("shell.application").shellexecute("%~dp0%~snx0","goto :begin","","runas",1)(window.close)&&exit

:begin
taskkill /f /im n2nedge.exe 2>nul 1>nul
echo n2nedge.exe 已发送退出指令
ping 127.0.0.1 -n 3 -w 1000 2>nul 1>nul
tasklist /nh|find /i "n2nedge.exe" 
if ERRORLEVEL 1 ( echo n2nedge.exe 已退出 ) else ( echo n2nedge.exe 还在运行 稍等几秒在执行一次 )
ping 127.0.0.1 -n 3 -w 1000 2>nul 1>nul
exit

test.bat

@echo off
chcp 936
cls
mode con:cols=60 lines=25
ping 192.168.100.1
echo:
echo:
echo:
if not %errorlevel% equ 0 (
    echo 错误 - 未能与服务器建立连接
    echo:
    tasklist /nh|find /i "n2nedge.exe"
    if ERRORLEVEL 1 (
        echo 错误 - N2N 未运行
        echo:
    ) else (
         echo 错误 - N2N 已经启动但无法连接
         echo:
    )
) else (
    echo 测试成功 可以进行游戏了
    echo:
)

ping 127.0.0.1 -n 10 -w 1000 2>nul 1>nul
exit

其他设置 暂时无用

这个命令比较新, 需要 powershell , 或者去改注册表...
设置网卡为 专用网络 (Private Network)

Get-NetIPInterface -AddressFamily IPv4 -ConnectionState Connected
Set-NetConnectionProfile -InterfaceAlias "OpenVPN TAP-Windows6" -NetworkCategory Private

下载的静态 zstd 不够静态

libzstd_static.lib(zstd_v06.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(zstd_v07.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(huf_decompress.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(fse_decompress.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(huf_compress.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(fse_compress.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(hist.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(zstd_v05.o) : error LNK2001: unresolved external symbol ___chkstk_ms
libzstd_static.lib(fse_compress.o) : error LNK2019: unresolved external symbol ___udivdi3 referenced in function _FSE_normalizeCount

因为下载的是 MinGW 编译的所以 MSBuild 无法使用, 这里我们使用 Visual Studio 2017 编译使用.

CentOS 7 服务端

vps: aliyun-ecs.t5-lc2m1.nano 1核512MB Centos 7 宽带25Mbps
服务器创建好了之后就可以开始执行了

yum install gcc-c git autoconf automake libtool git dhcp libzstd-devel nmap htop screen -y
git clone https://github.com/ntop/n2n.git --depth 1 --branch 2.8-stable
cd n2n
./autogen.sh
./configure CFLAGS="-O3 -march=native"
make && make install

装完之后就可以运行测试了

supernode -l 6666

服务器简单很多
记得开放 udp的端口.

#firewalld
firewall-cmd --zone=public --add-port=6666/udp --permanent
firewall-cmd --reload
#iptables
iptables -I INPUT -p udp --dport 6666 -j ACCEPT
service iptables save
service iptables restart
#ufw
ufw allow 6666/udp

搭建 DHCP 服务器 并把 N2N 设置为系统服务 (可选步骤)

限制社区连接 (可选)
这个文件可以参考 Communities.md
vim /home/n2n/n2n_community.list

AceSheep

supernode 配置文件
vim /home/n2n/n2n_config.conf

-l=3000
-c=/home/n2n/n2n_community.list

supernode 系统服务/守护程序
vim /etc/systemd/system/n2nserver.service

[Unit]
Description=n2n v.2.8.0.r1.53afd3c
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/sbin/supernode /home/n2n/n2n_config.conf
Restart=on-failure

[Install]
WantedBy=multi-user.target

启动测试, 查看状态

systemctl daemon-reload
systemctl start n2nserver
systemctl status n2nserver
nc -u 127.0.0.1 5645

N2N 搭建 DHCP 实现自动分配 IP地址

在服务器上启动一个 edge 作为分配 DHCP的接口

edge 配置文件
vim /home/n2n/n2n_edgedhcp.conf

-c=AceSheep
-z2
-A3
-k=8hKS1ew2VfX0M962
-l=0.0.0.0:3000
-d=n2ndhcp
-r
-a=192.168.50.0
-f

edge 系统服务/守护程序
vim /etc/systemd/system/n2ndhcp.service

[Unit]
Description=n2n DHCP
After=network.target n2nserver.service

[Service]
Type=simple
User=root
ExecStart=/usr/sbin/edge /home/n2n/n2n_edgedhcp.conf
Restart=on-failure

[Install]
WantedBy=multi-user.target

启动测试, 查看状态

systemctl daemon-reload
systemctl start n2ndhcp
systemctl status n2ndhcp
nc -u 127.0.0.1 5645

配置 DHCP 服务器
vim /etc/dhcp/dhcpd.conf

ddns-update-style interim;
ignore client-updates;

subnet 192.168.50.0 netmask 255.255.255.0 {
    range dynamic-bootp 192.168.50.100 192.168.50.200;
    option subnet-mask 255.255.255.0;
    default-lease-time 86400;    
    max-lease-time 864000;
    interface n2ndhcp;
}

host ftp_server {
    hardware ethernet 52:54:00:6f:f9:63;        # 指定主机 mac 地址
    fixed-address 192.168.50.254;               # 为指定主机分配的ip 
}

启动测试, 查看状态

systemctl start dhcpd
systemctl status dhcpd

都运行正常本地测试成功之后 设置为开机启动

systemctl enable dhcpd n2ndhcp n2nserver
reboot

2017-2 旧

Supernode:Centos 7
Edge:CentOS 7 ARM

安装

n2n 有两种协议,一种是v1协议,另一种是v2协议,两种是不兼容的。
我们最好使用编译安装.

Ubuntu / Debian 系列

sudo apt-get install subversion build-essential libssl-dev

CentOS 系列

yum install subversion gcc-c openssl-devel

不管你是什么系统,下面的代码都是一样的,我们使用v2协议。

svn co https://svn.ntop.org/svn/ntop/trunk/n2n
cd n2n/n2n_v2
make
sudo make install 

如果不出问题的话,我们就安装成功了。

配置

Supernode 配置
Supernode 并不需要 root 权限就可以运行,不过如果你是想使用小于 1024 的端口,就需要 root 权限了。

运行以下命令即可把supernode运行在后台。

supernode -l 12345

更多的用法如下

pi@raspberrypi ~ $ supernode -h
supernode usage
-l   Set UDP main listen port to 
-f          Run in foreground.
-v          Increase verbosity. Can be used multiple times.
-h          This help message.

Edge 配置
简单修改并运行以下命令即可运行edge

edge -d edge0 -a 10.0.0.10 -c [community] -k [encrypt key] -u 1000 -g 1000 -l [Supernode IP]:[Supernode Port]

例子

edge -d edge0 -a 10.0.0.10 -c myn2nline -k password123 -u 1000 -g 1000 -l 123.121.22.102:43321

更多的用法如下

pi@raspberrypi ~ $ edge -h
Welcome to n2n v.2.1.0 for unknown
Built on Sep 26 2015 16:11:34
Copyright 2007-09 - http://www.ntop.org

edge -d  -a [static:|dhcp:] -c  [-k  | -K ] [-s ] [-u  -g ][-f][-m ]
-l  [-p ] [-M ] [-r] [-E] [-v] [-t ] [-b] [-h]

-d                       | tun device name
-a                       | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'
-c                       | n2n community name the edge belongs to.
-k                       | Encryption key (ASCII) - also N2N_KEY=. Not with -K.
-K                       | Specify a key schedule file to load. Not with -k.
-s                       | Edge interface netmask in dotted decimal notation (255.255.255.0).
-l                       | Supernode IP:port
-b                       | Periodically resolve supernode IP
                          : (when supernodes are running on dynamic IPs)
-p                       | Fixed local UDP port.
-u                       | User ID (numeric) to use when privileges are dropped.
-g                       | Group ID (numeric) to use when privileges are dropped.
-f                       | Do not fork and run as a daemon; rather run in foreground.
-m                       | Fix MAC address for the TAP interface (otherwise it may be random)
                          : eg. -m 01:02:03:04:05:06
-M                       | Specify n2n MTU of edge interface (default 1400).
-r                       | Enable packet forwarding through n2n community.
-E                       | Accept multicast MAC addresses (default=drop).
-v                       | Make more verbose. Repeat as required.
-t                       | Management UDP Port (for multiple edges on a machine).

Environment variables:
  N2N_KEY                | Encryption key (ASCII). Not with -K or -k.

需要注意的是,-a 参数所指定的是你连接上 n2n 网络上的 IP 地址,显然这是不可以重复的。

你可以使用 DHCP 服务器进行分配 IP ,使用 -a dhcp:10.0.0.22 意思就是使用 10.0.0.22 作为 DHCP 服务器进行 IP 地址的分配,而 10.0.0.22 这台服务器也是需要连接上同一个 Edge 的。

更多的用法你们可以自己参考上面的文档。

错误解决
n2n[4405]: ERROR: ioctl() [Operation not permitted][-1]
在我的树莓派上面运行的时候出现了上面的问题,显然这是由于权限不足导致的,因为 edge 需要 root 权限来创建一个 TAP 接口,因此我们需要通过 sudo 来运行。


新原文
N2N Windows编译过程。。。以及遇到的一些坑(这篇不是网上复制的。绝对有用)
How to build x86 and/or x64 on Windows from command line with CMAKE?
CMake not able to find OpenSSL library
n2n Build on Windows
Command-line installation of OpenVPN
使用N2N搭建虚拟局域网联机游戏(服务端)
LAN discovery
Enable file and print sharing command line - how to enable it just for profile=private
Static linking of OpenSSL Crypto in CMake
Minecraft Local Server Discovery – Can’t find LAN games?
N2N组建虚拟局域网联机遇到搜不到房间的问题一例
Is static library not enough static? - zstd
Windows Network Public To Private.sh
Enable file and print sharing command line - how to enable it just for profile=private

旧原文
How to enable broadcast and multicast support on Amazon (AWS) EC2 n2n
www.buckhill.co.uk 网页离线缓存
N2N Edge GUI 文件很旧 备份下载:n2neg.zip


扫描二维码,在手机上阅读!

添加新评论