├── .dockerignore ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── NSmartProxyNew.png ├── README.md ├── README_EN.md ├── README_SERVER.md ├── README_SERVER_CN.md ├── THEORETIC.doc ├── _config.yml ├── azure-pipelines.yml ├── imgs ├── servicecn.png ├── serviceen.png └── supervisor.png ├── plugins └── NSmartProxyFTP │ ├── FtpClient.cs │ ├── FtpRequest.cs │ ├── FtpServer.cs │ ├── FtpUser.cs │ ├── NSmartProxyFTP.csproj │ ├── Program.cs │ ├── appsettings.json │ └── log4net.config ├── sh.exe.stackdump ├── src ├── NSmartProxy.ClientRouter │ ├── Authorize │ │ └── UserCacheManager.cs │ ├── ClientAppWorker.cs │ ├── Dispatchers │ │ └── NSPDispatcher.cs │ ├── NSmartProxy.ClientRouter.csproj │ ├── Router.cs │ ├── ServerConnectionManager.cs │ └── ServiceClientListCollection.cs ├── NSmartProxy.Data │ ├── ByteSerializeableObject.cs │ ├── Config │ │ ├── CABoundConfig.cs │ │ ├── NSPClientConfig.cs │ │ ├── NSPServerConfig.cs │ │ └── ServerBoundConfig.cs │ ├── DBEntites │ │ └── User.cs │ ├── DTOs │ │ ├── CertDTO.cs │ │ ├── FileDTO.cs │ │ ├── FileUploadDTO.cs │ │ ├── LoginFormClientResult.cs │ │ ├── ServerPortsDTO.cs │ │ ├── ServerStatusDTO.cs │ │ ├── UserDTO.cs │ │ └── UserStatusDTO.cs │ ├── HttpResult.cs │ ├── Models │ │ ├── App.cs │ │ ├── ClientApp.cs │ │ ├── ClientIdAppId.cs │ │ ├── ClientModel.cs │ │ ├── ClientNewAppRequest.cs │ │ ├── ClientUserCache.cs │ │ └── LoginInfo.cs │ ├── NSmartProxy.Data.csproj │ ├── ServerProtocol.cs │ ├── ServerStatus.cs │ └── TokenClaims.cs ├── NSmartProxy.Infrastructure │ ├── ConfigHelper.cs │ ├── ConsoleHelper.cs │ ├── DatetimeHelper.cs │ ├── EncryptHelper.cs │ ├── Extensions │ │ ├── AsyncExtension.cs │ │ ├── HttpServer │ │ │ ├── HttpServer.cs │ │ │ ├── HttpServerAttributes.cs │ │ │ └── HttpServer_MIMEs.cs │ │ ├── StreamExtension.cs │ │ └── TcpPipelinesExt.cs │ ├── HtmlUtil.cs │ ├── I18N.cs │ ├── Interfaces │ │ ├── IHttpServerContext.cs │ │ ├── ILogger.cs │ │ └── IWebController.cs │ ├── LiteNetLib │ │ ├── BaseChannel.cs │ │ ├── ConnectionRequest.cs │ │ ├── INetEventListener.cs │ │ ├── Layers │ │ │ ├── Crc32cLayer.cs │ │ │ ├── PacketLayerBase.cs │ │ │ └── XorEncryptLayer.cs │ │ ├── NatPunchModule.cs │ │ ├── NetConstants.cs │ │ ├── NetDebug.cs │ │ ├── NetExceptions.cs │ │ ├── NetManager.cs │ │ ├── NetPacket.cs │ │ ├── NetPacketPool.cs │ │ ├── NetPeer.cs │ │ ├── NetSocket.cs │ │ ├── NetStatistics.cs │ │ ├── NetUtils.cs │ │ ├── ReliableChannel.cs │ │ ├── SequencedChannel.cs │ │ ├── SimpleChannel.cs │ │ └── Utils │ │ │ ├── CRC32C.cs │ │ │ ├── FastBitConverter.cs │ │ │ ├── INetSerializable.cs │ │ │ ├── NetDataReader.cs │ │ │ ├── NetDataWriter.cs │ │ │ ├── NetPacketProcessor.cs │ │ │ ├── NetSerializer.cs │ │ │ ├── NtpPacket.cs │ │ │ └── NtpRequest.cs │ ├── NSmartProxy.Infrastructure.csproj │ ├── NetworkUtil.cs │ ├── RandomHelper.cs │ ├── Shared │ │ ├── Global.cs │ │ ├── IDbOperator.cs │ │ ├── NSPVersion.cs │ │ ├── NSPVersion.tt │ │ └── SecurityTcpClient.cs │ ├── Snappy │ │ ├── Snappy.cs │ │ ├── SnappyCompressor.cs │ │ ├── SnappyDecompressor.cs │ │ ├── SnappyStream.cs │ │ └── Utilities.cs │ └── StringUtil.cs ├── NSmartProxy.NUnitTest │ ├── CAGenerate.cs │ ├── HttpAPI.cs │ ├── NSmartProxy.NUnitTest.csproj │ └── P2PPunch.cs ├── NSmartProxy.P2PClient46 │ ├── App.config │ ├── NSmartProxy.P2PClient46.csproj │ ├── Program.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── NSmartProxy.P2PHost46 │ ├── App.config │ ├── NSmartProxy.P2PHost46.csproj │ ├── Program.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── NSmartProxy.ServerHost │ ├── Dockerfile │ ├── NSmartProxy.ServerHost.csproj │ ├── Program.cs │ ├── ServerHost.cs │ ├── appsettings.json │ └── log4net.config ├── NSmartProxy.sln ├── NSmartProxy │ ├── Authorize │ │ └── NSPServerContext.cs │ ├── ClientConnectionManager.cs │ ├── Database │ │ ├── HashFile.cs │ │ ├── LiteDbOperator.cs │ │ ├── NSmartDb.cs │ │ └── SequenceFile.cs │ ├── Extension │ │ ├── CAGen.cs │ │ ├── HttpServer_APIs.cs │ │ └── PeekableBufferBlock.cs │ ├── NSPApp.cs │ ├── NSPAppGroup.cs │ ├── NSPClient.cs │ ├── NSmartProxy.csproj │ ├── Server.cs │ ├── ServerModels.cs │ ├── TcpTunnel.cs │ └── Web │ │ ├── Chart.min.js │ │ ├── NSmartProxyNew.png │ │ ├── Web.config │ │ ├── bootstrap-table-expandable.js │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.min.css │ │ ├── bootstrapValidator.css │ │ ├── bootstrapValidator.js │ │ ├── config.html │ │ ├── config.js │ │ ├── connections.html │ │ ├── connections.js │ │ ├── dashboard.css │ │ ├── dashboard.html │ │ ├── dashboard.js │ │ ├── favicon.ico │ │ ├── feather.min.js │ │ ├── jquery-slim.min.js │ │ ├── loading-s.gif │ │ ├── login.html │ │ ├── logs.html │ │ ├── logs.js │ │ ├── main.html │ │ ├── main.js │ │ ├── signin.css │ │ ├── users.html │ │ └── users.js ├── NSmartProxy4Windows.sln ├── NSmartProxyClient │ ├── Dockerfile │ ├── NSmartProxyClient.cs │ ├── NSmartProxyClient.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.json │ └── log4net.config ├── NSmartProxyWinService │ ├── App.config │ ├── NSPClientService.Designer.cs │ ├── NSPClientService.cs │ ├── NSPClientService.resx │ ├── NSmartProxyWinService.csproj │ ├── Program.cs │ ├── ProjectInstaller.Designer.cs │ ├── ProjectInstaller.cs │ ├── ProjectInstaller.resx │ ├── Properties │ │ └── AssemblyInfo.cs │ └── packages.config ├── NSmartProxyWinform │ ├── AboutBox.Designer.cs │ ├── AboutBox.cs │ ├── AboutBox.resx │ ├── App.config │ ├── ClientMngr.Designer.cs │ ├── ClientMngr.cs │ ├── ClientMngr.resx │ ├── FodyWeavers.xml │ ├── FodyWeavers.xsd │ ├── Log4netLogger.cs │ ├── Login.Designer.cs │ ├── Login.cs │ ├── Login.resx │ ├── NSmartProxyWinform.csproj │ ├── Program.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ ├── Resources │ │ ├── NSmartProxyNew.png │ │ ├── Permission_12796.png │ │ ├── UserProfilenode_8706.png │ │ ├── base_checkmark_32.png │ │ ├── servicepaused.ico │ │ ├── servicerunning.ico │ │ └── servicestopped.ico │ ├── System │ │ └── AutoStartup.cs │ ├── Util │ │ ├── HotKey.cs │ │ ├── TextBoxEx.cs │ │ └── WinServiceHelper.cs │ ├── appsettings.json │ ├── i18n │ │ ├── en.txt │ │ ├── ol.txt │ │ └── zh.txt │ ├── log4net.config │ ├── nsp.ico │ └── packages.config ├── TestBed │ ├── NSmartProxy.ConsoleTest │ │ ├── Class1.cs │ │ ├── Echoexcample.cs │ │ ├── HolePunchTest.cs │ │ ├── HolePunchTest1.cs │ │ ├── NSmartProxy.ConsoleTest.csproj │ │ └── Program.cs │ ├── NSmartProxy.P2PClient - 副本 │ │ ├── NSmartProxy.P2PClient.csproj │ │ └── Program.cs │ └── NSmartProxy.P2PClient │ │ ├── NSmartProxy.P2PClient.csproj │ │ └── Program.cs ├── build.cmd ├── build_simple.cmd ├── build_test.cmd ├── deploy.cmd └── global.temp ├── test ├── TcpClient │ ├── Class1.cs │ ├── Program.cs │ └── TcpClient.csproj ├── TcpServer │ ├── Class1.cs │ ├── Program.cs │ └── TcpServer.csproj ├── TestBed.sln ├── UdpClient │ ├── Program.cs │ └── UdpClient.csproj ├── UdpServer │ ├── Program.cs │ └── UdpServer.csproj └── auto_test.cmd ├── theo.png └── wx ├── .gitignore ├── CMakeLists.txt ├── Info.plist ├── LICENSE ├── MainFrame.cpp ├── MainFrame.generated.cpp ├── MainFrame.generated.h ├── MainFrame.h ├── README.md ├── gui.fbp ├── main.cpp └── main.exe.manifest /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://tmoonlight.github.io/100lines/111.html'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | .vs 9 | bin/ 10 | tmp/ 11 | *.tmp 12 | *.bak 13 | *.swp 14 | *~.nib 15 | local.properties 16 | .classpath 17 | .settings/ 18 | .loadpath 19 | 20 | # External tool builders 21 | .externalToolBuilders/ 22 | 23 | # Locally stored "Eclipse launch configurations" 24 | *.launch 25 | 26 | # CDT-specific 27 | .cproject 28 | 29 | # PDT-specific 30 | .buildpath 31 | 32 | 33 | ################# 34 | ## Visual Studio 35 | ################# 36 | 37 | ## Ignore Visual Studio temporary files, build results, and 38 | ## files generated by popular Visual Studio add-ons. 39 | 40 | # User-specific files 41 | *.suo 42 | *.user 43 | *.sln.docstates 44 | 45 | # Build results 46 | 47 | [Dd]ebug/ 48 | [Rr]elease/ 49 | x64/ 50 | build/ 51 | [Bb]in/ 52 | [Oo]bj/ 53 | 54 | # MSTest test Results 55 | [Tt]est[Rr]esult*/ 56 | [Bb]uild[Ll]og.* 57 | 58 | *_i.c 59 | *_p.c 60 | *.ilk 61 | *.meta 62 | *.obj 63 | *.pch 64 | *.pdb 65 | *.pgc 66 | *.pgd 67 | *.rsp 68 | *.sbr 69 | *.tlb 70 | *.tli 71 | *.tlh 72 | *.tmp 73 | *.tmp_proj 74 | *.log 75 | *.vspscc 76 | *.vssscc 77 | .builds 78 | *.pidb 79 | *.log 80 | *.scc 81 | 82 | # Visual C++ cache files 83 | ipch/ 84 | *.aps 85 | *.ncb 86 | *.opensdf 87 | *.sdf 88 | *.cachefile 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | 102 | # TeamCity is a build add-in 103 | _TeamCity* 104 | 105 | # DotCover is a Code Coverage Tool 106 | *.dotCover 107 | 108 | # NCrunch 109 | *.ncrunch* 110 | .*crunch*.local.xml 111 | 112 | # Installshield output folder 113 | [Ee]xpress/ 114 | 115 | # DocProject is a documentation generator add-in 116 | DocProject/buildhelp/ 117 | DocProject/Help/*.HxT 118 | DocProject/Help/*.HxC 119 | DocProject/Help/*.hhc 120 | DocProject/Help/*.hhk 121 | DocProject/Help/*.hhp 122 | DocProject/Help/Html2 123 | DocProject/Help/html 124 | 125 | # Click-Once directory 126 | publish/ 127 | 128 | # Publish Web Output 129 | *.Publish.xml 130 | *.pubxml 131 | 132 | # NuGet Packages Directory 133 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 134 | packages/ 135 | 136 | # Windows Azure Build Output 137 | csx 138 | *.build.csdef 139 | 140 | # Windows Store app package directory 141 | AppPackages/ 142 | 143 | # Others 144 | sql/ 145 | *.Cache 146 | ClientBin/ 147 | [Ss]tyle[Cc]op.* 148 | ~$* 149 | *~ 150 | *.dbmdl 151 | *.[Pp]ublish.xml 152 | *.pfx 153 | *.publishsettings 154 | 155 | # RIA/Silverlight projects 156 | Generated_Code/ 157 | 158 | # Backup & report files from converting an old project file to a newer 159 | # Visual Studio version. Backup files are not needed, because we have git ;-) 160 | _UpgradeReport_Files/ 161 | Backup*/ 162 | UpgradeLog*.XML 163 | UpgradeLog*.htm 164 | 165 | # SQL Server files 166 | App_Data/*.mdf 167 | App_Data/*.ldf 168 | 169 | ############# 170 | ## Windows detritus 171 | ############# 172 | 173 | # Windows image file caches 174 | Thumbs.db 175 | ehthumbs.db 176 | 177 | # Folder config file 178 | Desktop.ini 179 | 180 | # Recycle Bin used on file shares 181 | $RECYCLE.BIN/ 182 | 183 | # Mac crap 184 | .DS_Store 185 | 186 | 187 | ############# 188 | ## Python 189 | ############# 190 | 191 | *.py[co] 192 | 193 | # Packages 194 | *.egg 195 | *.egg-info 196 | dist/ 197 | build/ 198 | eggs/ 199 | parts/ 200 | var/ 201 | sdist/ 202 | develop-eggs/ 203 | .installed.cfg 204 | 205 | # Installer logs 206 | pip-log.txt 207 | 208 | # Unit test / coverage reports 209 | .coverage 210 | .tox 211 | 212 | #Translations 213 | *.mo 214 | 215 | #Mr Developer 216 | .mr.developer.cfg 217 | /wx/.vscode 218 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 NSmartProxy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NSmartProxyNew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/NSmartProxyNew.png -------------------------------------------------------------------------------- /README_SERVER.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # NSmartProxy Server 4 | 5 | Here is the installation method of NSmartProxy server (Linux, windows, MacOS are compatible)
6 | 7 | ## Startup preparation 8 | * First of all, you need a server with a separate IP, the following installation process is performed on this machine: 9 | #### Linux/Windows/MacOS 10 | 1. Install [.NET Core Environment](https://dotnet.microsoft.com/download)
11 | 2. Download the latest version of [NSmartProxy](https://github.com/tmoonlight/NSmartProxy/releases) 12 | 13 | #### Docker 14 | * You can run the nspserver directly without having to install the runtime. Four sets of ports are required to run the docker image: configuration port, reverse connection port, API service port and consumer port: 15 | ``` 16 | sudo docker pull tmoonlight/nspserver 17 | sudo docker run --name mynspserver -dit -p 7842:7842 -p 7841:7841 -p 12309:12309 -p 20000-20050 tmoonlight/nspserver 18 | ``` 19 | 20 | ## Instructions 21 | 1. Unzip the package of NSmartProxy server. 22 | 2. Open the appsettings.json file in the installation directory, set the reverse connection port and configure the service port:
23 | ``` 24 | { 25 |   "ReversePort": 7842, //Reverse connection port 26 |   "ConfigPort": 7841, //Configure the service port 27 |   "WebAPIPort": 12309 //API service port 28 | } 29 | ``` 30 |
31 | 3. Run NSmartProxy Server
32 | 33 | 34 | * Linux/MacOS: 35 | Change directory to the installation directory ,then execute the following command: 36 | ``` 37 | sudo dotnet NSmartProxy.ServerHost.dll 38 | ``` 39 | * Windows: 40 | Press Windows+R to open the “Run” box. Type “cmd” into the box and then press Ctrl+Shift+Enter to run the command as an administrator. 41 | Change directory to the installation directory ,then execute the following command: 42 | ``` 43 | dotnet NSmartProxy.ServerHost.dll 44 | ``` 45 | 46 | 47 | In the next step,you can log in to http://youraddress:12309 and enter the web terminal. The default user password is admin/admin. 48 | 49 | 50 | 51 | And enter the server to perform various management operations. 52 | 53 | 54 | -------------------------------------------------------------------------------- /README_SERVER_CN.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # NSmartProxy ServerHost 5 | 6 | 这里介绍NSmartProxy服务端的安装方法(linux,windows,MacOS均适用)
7 | 8 | ## 启动准备 9 | * 首先你需要一台具备独立IP的服务器,以下安装过程均在此机器上执行: 10 | #### Linux/Windows/MacOS 11 | 1.安装[.NET Core环境](https://dotnet.microsoft.com/download)
12 | 2.下载最新版的[NSmartProxy](https://github.com/tmoonlight/NSmartProxy/releases 13 | 14 | #### Docker 15 | * 无需安装运行时,直接拉取镜像即可运行,运行镜像时需要4组端口:配置端口,反向连接端口,API服务端口,以及使用端口 : 16 | ``` 17 | sudo docker pull tmoonlight/nspserver 18 | sudo docker run --name mynspserver -dit -p 7842:7842 -p 7841:7841 -p 12309:12309 -p 20000-20050 tmoonlight/nspserver 19 | ``` 20 | 21 | ## 使用方法 22 | 1. 解压缩NSmartProxy服务端的压缩包。 23 | 2. 打开安装目录下的appsettings.json文件,设置反向连接端口和配置服务端口:
24 | ``` 25 | { 26 | "ReversePort": 7842, //反向连接端口 27 | "ConfigPort": 7841, //配置服务端口 28 | "WebAPIPort": 12309 //API服务端口 29 | } 30 | ``` 31 |
32 | 3. 运行NSmartProxy
33 | 34 | 第一步 cd到安装目录
35 | 第二步 执行以下命令 36 | * Linux/MacOS: 37 | ``` 38 | sudo dotnet NSmartProxy.ServerHost.dll 39 | ``` 40 | * Windows: 41 | 点击 Win+R 打开运行窗口. 输入 “cmd” 按下 Ctrl+Shift+Enter打开管理员身份运行的命令行窗口。 cd到安装目录,运行如下指令: 42 | 43 | ``` 44 | dotnet NSmartProxy.ServerHost.dll 45 | ``` 46 | 47 | 第三步 登陆http://ip:12309 进入web端,出厂用户密码为admin/admin 48 | 49 | 50 | 51 | 第四步 进入服务端对用户进行各种管理操作 52 | 53 | 54 | 55 | * 注册为后台服务
56 | 您还可以将NSmartProxy客户端注册为一个后台服务,方法如下: 57 | 以管理员身份打开命令行后,运行以下指令进行服务的注册和卸载: 58 | ``` 59 | rem 注册windows服务 60 | dotnet NSmartProxy.ServerHost.dll action:install 61 | ``` 62 | 63 | ``` 64 | rem 卸载windows服务 65 | dotnet NSmartProxy.ServerHost.dll action:uninstall 66 | ``` 67 | -------------------------------------------------------------------------------- /THEORETIC.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/THEORETIC.doc -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # ASP.NET Core (.NET Framework) 2 | # Build and test ASP.NET Core projects targeting the full .NET Framework. 3 | # Add steps that publish symbols, save build artifacts, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'ubuntu-latest' 11 | 12 | variables: 13 | solution: '**/*.sln' 14 | buildPlatform: 'Any CPU' 15 | buildConfiguration: 'Release' 16 | clientImageName: 'nspclient' 17 | serverImageName: 'nspserver' 18 | clientProjectName: 'NSmartProxyClient' 19 | serverProjectName: 'NSmartProxy.ServerHost' 20 | 21 | steps: 22 | # - task: NuGetToolInstaller@0 23 | 24 | # - task: NuGetCommand@2 25 | # inputs: 26 | # restoreSolution: '$(solution)' 27 | 28 | # - task: VSBuild@1 29 | # inputs: 30 | # solution: '$(solution)' 31 | # msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(System.DefaultWorkingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' 32 | # platform: '$(buildPlatform)' 33 | # configuration: '$(buildConfiguration)' 34 | 35 | # - task: VSTest@2 36 | # inputs: 37 | # platform: '$(buildPlatform)' 38 | # configuration: '$(buildConfiguration)' 39 | - bash: | 40 | mkdir ./build 41 | mkdir ./build/$(clientImageName) 42 | mkdir ./build/$(clientImageName)/$(clientProjectName) 43 | mkdir ./build/nspserver 44 | mkdir ./build/nspserver/NSmartProxy.ServerHost 45 | displayName: Create build directory 46 | workingDirectory: '$(System.DefaultWorkingDirectory)/' 47 | 48 | - task: DotNetCoreCLI@2 49 | inputs: 50 | command: 'publish' 51 | publishWebProjects: false 52 | projects: './src/NSmartProxy.ServerHost/NSmartProxy.ServerHost.csproj' 53 | arguments: ' --output $(System.DefaultWorkingDirectory)/build/nspserver /p:PublishTrimmed=false' 54 | workingDirectory: '$(System.DefaultWorkingDirectory)/' 55 | zipAfterPublish: false 56 | 57 | - task: DotNetCoreCLI@2 58 | inputs: 59 | command: 'publish' 60 | publishWebProjects: false 61 | projects: './src/NSmartProxyClient/NSmartProxyClient.csproj' 62 | arguments: ' --output $(System.DefaultWorkingDirectory)/build/nspclient /p:PublishTrimmed=false' 63 | workingDirectory: '$(System.DefaultWorkingDirectory)/' 64 | zipAfterPublish: false 65 | 66 | 67 | - task: Bash@3 68 | inputs: 69 | targetType: 'inline' 70 | script: | 71 | docker login -u $(dhName) -p $(dhPwd) 72 | docker build . -t nspclient 73 | docker tag nspclient tmoonlight/nspclient 74 | docker push tmoonlight/nspclient 75 | workingDirectory: '$(System.DefaultWorkingDirectory)/build/nspclient/NSmartProxyClient' 76 | 77 | - task: Bash@3 78 | inputs: 79 | targetType: 'inline' 80 | script: | 81 | docker login -u $(dhName) -p $(dhPwd) 82 | docker build . -t nspserver 83 | docker tag nspserver tmoonlight/nspserver 84 | docker push tmoonlight/nspserver 85 | workingDirectory: '$(System.DefaultWorkingDirectory)/build/nspserver/$(serverProjectName)' 86 | 87 | -------------------------------------------------------------------------------- /imgs/servicecn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/imgs/servicecn.png -------------------------------------------------------------------------------- /imgs/serviceen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/imgs/serviceen.png -------------------------------------------------------------------------------- /imgs/supervisor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/imgs/supervisor.png -------------------------------------------------------------------------------- /plugins/NSmartProxyFTP/FtpUser.cs: -------------------------------------------------------------------------------- 1 | //作者:Mcdull 2 | //说明:FTP账号类 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Configuration; 8 | 9 | namespace FtpServer 10 | { 11 | sealed class User 12 | { 13 | public bool isLogin { get; set; } 14 | public string username { get; set; } 15 | public string password { get; set; } 16 | public string workingDir { get; set; } 17 | } 18 | 19 | sealed class UserElement 20 | { 21 | public string username 22 | { 23 | get; set; 24 | } 25 | public string password 26 | { 27 | get; set; 28 | } 29 | public string rootDir 30 | { 31 | get; set; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugins/NSmartProxyFTP/NSmartProxyFTP.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /plugins/NSmartProxyFTP/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProviderWebPort": 12309, 3 | "ProviderAddress": "2017studio.imwork.net", 4 | "FtpPort": 5555, 5 | "PasvPort": 5379, 6 | "FtpMaxConnect": 2, //FTP最大连接数 7 | //FTP用户,可以配置多个 8 | "FtpUsers": [ 9 | { 10 | "username": "admin", 11 | "password": "654123", 12 | "rootDir": "d:\\" 13 | } 14 | ], 15 | 16 | //反向代理客户端,可以配置多个 17 | "Clients": [ 18 | 19 | //{ 20 | // "IP": "127.0.0.1", 21 | // "TargetServicePort": "82", 22 | // "Host": "haha.tmoonlight.top", 23 | // "Protocol": "HTTP", 24 | // "ConsumerPort": "443", 25 | // "Description": "测试备注" 26 | //}, 27 | 28 | { 29 | "IP": "127.0.0.1", 30 | "TargetServicePort": "5555", 31 | "ConsumerPort": "20006" 32 | }, 33 | { 34 | "IP": "127.0.0.1", 35 | "TargetServicePort": "5379", 36 | "ConsumerPort": "20007" 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /plugins/NSmartProxyFTP/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /sh.exe.stackdump: -------------------------------------------------------------------------------- 1 | Stack trace: 2 | Frame Function Args 3 | 00000010002 0018006021E (00180241C10, 001802340B9, 00000010002, 000FFFFBA20) 4 | 00000010002 00180048859 (00000000002, 00180329138, 00000000002, 00180329138) 5 | 00000010002 00180048892 (00000000002, 00180329448, 00000010002, 00000000008) 6 | 00000010002 001800598BC (000FFFFCC72, 000FFFFCC55, 00000000000, 001802343AF) 7 | 000FFFFCCD0 00180059960 (645C655C725C635C, 695C745C6E5C655C, 6D5C2D5C6C5C615C, 675C615C6E5C615C) 8 | 000FFFFCCD0 00180048FE1 (00000000000, 00000000000, 00000000000, 00000000000) 9 | 00000000000 00180047963 (00000000000, 00000000000, 00000000000, 00000000000) 10 | 000FFFFFFF0 00180047A14 (00000000000, 00000000000, 00000000000, 00000000000) 11 | End of stack trace 12 | -------------------------------------------------------------------------------- /src/NSmartProxy.ClientRouter/ClientAppWorker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.Sockets; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Client 7 | { 8 | public class ClientAppWorker 9 | { 10 | //private bool isWorking = false; 11 | 12 | //public List TcpClientGroup = new List(); 13 | public TcpClient Client;//TODO 还是需要把这里改成复数 14 | public int AppId; //1~255 15 | public int Port; //0~65535 16 | 17 | //public bool IsWorking { get => isWorking;} 18 | 19 | //public void StartWork() 20 | //{ 21 | // isWorking = true; 22 | //} 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NSmartProxy.ClientRouter/NSmartProxy.ClientRouter.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0;netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/NSmartProxy.ClientRouter/ServiceClientListCollection.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Client 7 | { 8 | public class ServiceClientListCollection : Dictionary 9 | { 10 | /// 11 | /// 通过appid查询服务节点 12 | /// 13 | /// 14 | /// 15 | public ClientAppWorker GetAppFromPort(int appid) 16 | { 17 | if (this.ContainsKey(appid)) 18 | { 19 | return this[appid]; 20 | } 21 | else 22 | { 23 | return null; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/ByteSerializeableObject.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxy.Data 2 | { 3 | public abstract class ByteSerializeableObject 4 | { 5 | public abstract byte[] ToBytes(); 6 | /// 7 | /// 整型转双字节 8 | /// 9 | /// 10 | /// 11 | public byte[] IntTo2Bytes(int number) 12 | { 13 | byte[] bytes = new byte[2]; 14 | bytes[0] = (byte)(number / 256); 15 | bytes[1] = (byte)(number % 256); 16 | return bytes; 17 | } 18 | 19 | /// 20 | /// 双字节转整型 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static int DoubleBytesToInt(byte hByte, byte lByte) 26 | { 27 | return (hByte << 8) + lByte; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Config/CABoundConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data 6 | { 7 | public class CABoundConfig 8 | { 9 | public int ClientId; 10 | public int AppId; 11 | public string Path; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Config/NSPClientConfig.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy.Data; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using Newtonsoft.Json; 6 | 7 | namespace NSmartProxy.Data 8 | { 9 | public class NSPClientConfig 10 | { 11 | [JsonIgnore] 12 | public int ReversePort; //代理转发服务端口 13 | [JsonIgnore] 14 | public int ConfigPort; //配置服务端口 15 | 16 | public bool UseServerControl = true; //启用服务端配置 17 | public string ProviderAddress; //代理服务器地址 18 | public int ProviderWebPort; //web管理端的端口,默认12309 //TODO 暂时写死,以后再改 19 | public List Clients = new List();//客户端app 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Config/NSPServerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.Config 6 | { 7 | public class NSPServerConfig 8 | { 9 | public int ReversePort = 19974; //服务端代理转发端口 10 | public int ConfigPort = 12308; //服务端配置通讯端口 11 | public int WebAPIPort = 12309; //远端管理端口 12 | public int ReversePort_Out = 0; 13 | public int ConfigPort_Out = 0; 14 | public bool supportAnonymousLogin = true; 15 | 16 | //[] 17 | public ServerBoundConfig BoundConfig = new ServerBoundConfig();//用户端口绑定列表 18 | //public List CABoundConfigList = new List();//host->证书路径 19 | public Dictionary CABoundConfig = new Dictionary();//证书绑定列表 端口->证书路径,为了方便扩展这里使用字符串类型 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Config/ServerBoundConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data 6 | { 7 | /// 8 | /// 服务的端口绑定配置以及用户的banlist 9 | /// 10 | [Serializable] 11 | public class ServerBoundConfig 12 | { 13 | public HashSet UsersBanlist = new HashSet(); 14 | public Dictionary UserPortBounds = new Dictionary(); 15 | 16 | 17 | } 18 | 19 | public class UserPortBound 20 | { 21 | public string UserId; 22 | public List Bound = new List(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DBEntites/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO.Pipes; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Data.DBEntities 7 | { 8 | public class User 9 | { 10 | public string userId; 11 | public string userPwd; 12 | public string userName; 13 | public string regTime; 14 | public string isAdmin; 15 | public string isAnonymous; //1表示是 0表示否,匿名用户 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/CertDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.DTOs 6 | { 7 | /// 8 | /// 证书DTO 9 | /// 10 | public class CertDTO 11 | { 12 | public int Port; 13 | public string CreateTime; 14 | public string ToTime; 15 | public string Hosts; 16 | public string Extensions; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/FileDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Data.DTOs 7 | { 8 | public class FileUploadDTO 9 | { 10 | public FileInfo FileInfo; 11 | public string FileName; 12 | //public string Host; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/FileUploadDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Data.DTOs 7 | { 8 | public class FileDTO 9 | { 10 | public FileStream FileStream; 11 | public string FileName; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/LoginFormClientResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.DTOs 6 | { 7 | public class LoginFormClientResult 8 | { 9 | public string Token { get; set; } 10 | public string Version { get; set; } 11 | public string Userid { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/ServerPortsDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data 6 | { 7 | public class ServerPortsDTO 8 | { 9 | public int ReversePort = 19974; //服务端代理转发端口 10 | public int ConfigPort = 12308; //服务端配置通讯端口 11 | public int WebAPIPort = 12309; //远端管理端口 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/ServerStatusDTO.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxy.Data.DTOs 2 | { 3 | public class ServerStatusDTO 4 | { 5 | public long totalReceivedBytes; 6 | public long totalSentBytes; 7 | public long connectCount; 8 | } 9 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/UserDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.DTOs 6 | { 7 | public class UserDTO 8 | { 9 | public string userId; 10 | public string userPwd; 11 | public string userName; 12 | public string regTime; 13 | public string isAdmin; 14 | public string boundPorts;//锁定的端口,不会被其他任何用户使用 15 | public string isAnonymous; //1表示是 0表示否,匿名用户 16 | public string isBanned; //被断开 17 | public string isOnline; //正在连接中 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/DTOs/UserStatusDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.DTOs 6 | { 7 | public class UserStatusDTO 8 | { 9 | public int offlineUsersCount; 10 | public int onlineUsersCount; 11 | public int banUsersCount; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/HttpResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data 6 | { 7 | public static class HttpResultExtension 8 | { 9 | /// 10 | /// 包装对象为返回结果,即使是null也能包装 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static HttpResult Wrap(this T obj) 16 | { 17 | if (obj is Exception) 18 | { 19 | Exception ex = obj as Exception; 20 | return new HttpResult() 21 | { 22 | State = 0, 23 | Msg = ex.ToString() 24 | }; 25 | } 26 | 27 | return new HttpResult() 28 | { 29 | State = 1, 30 | Msg = "", 31 | Data = obj 32 | }; 33 | } 34 | } 35 | 36 | public class HttpResult 37 | { 38 | public HttpResult() 39 | { 40 | 41 | } 42 | 43 | //1代表成功 0代表失败 44 | private int state; 45 | private string msg; 46 | private T data; 47 | 48 | public int State { get => state; set => state = value; } 49 | 50 | /// 51 | /// 附加信息,一般是错误信息,或者是提示信息 52 | /// 53 | public string Msg { get => msg; set => msg = value; } 54 | public T Data { get => data; set => data = value; } 55 | public static HttpResult NullSuccessResult { get; } = new HttpResult() { state = 1 }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/App.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxy.Data 2 | { 3 | /// 4 | /// 一个App 5 | /// 6 | public class App 7 | { 8 | //id需要大于1,否则会有很多问题 9 | public int AppId; //1 10 | public int Port; //2 11 | } 12 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/ClientApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.Serialization; 4 | using System.Runtime.Serialization.Formatters.Binary; 5 | using Newtonsoft.Json; 6 | using Newtonsoft.Json.Converters; 7 | 8 | namespace NSmartProxy.Data 9 | { 10 | public enum Protocol : byte 11 | { 12 | TCP = 0x00, 13 | HTTP = 0x01, //同时代表HTTP/HTTPS 14 | //HTTPS = 0x02, 15 | UDP = 0x04 16 | } 17 | 18 | [Serializable] 19 | public class ClientApp : ICloneable 20 | { 21 | [JsonIgnore] 22 | public int AppId { get; set; } 23 | public string IP { get; set; } 24 | public int TargetServicePort { get; set; } 25 | public int ConsumerPort { get; set; } 26 | public bool IsCompress { get; set; } 27 | 28 | [JsonConverter(typeof(StringEnumConverter))] 29 | public Protocol Protocol { get; set; } 30 | public string Host { get; set; } 31 | public string Description { get; set; } 32 | 33 | public object Clone() 34 | { 35 | //返回深拷贝(不使用BinaryFormatter) 36 | return new ClientApp 37 | { 38 | AppId = AppId, 39 | IP = IP, 40 | TargetServicePort = TargetServicePort, 41 | ConsumerPort = ConsumerPort, 42 | IsCompress = IsCompress, 43 | Protocol = Protocol, 44 | Host = Host, 45 | Description = Description 46 | }; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/ClientIdAppId.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxy.Data 2 | { 3 | /// 4 | /// 客户端和appid的组合 5 | /// 6 | public class ClientIdAppId : ByteSerializeableObject 7 | { 8 | public int ClientId; //2 9 | public int AppId; //1 10 | public override byte[] ToBytes() 11 | { 12 | byte[] bytes = new byte[3]; 13 | byte[] clientIdBytres = IntTo2Bytes(ClientId); 14 | bytes[0] = clientIdBytres[0]; 15 | bytes[1] = clientIdBytres[1]; 16 | bytes[2] = (byte)AppId; 17 | return bytes; 18 | } 19 | 20 | public static ClientIdAppId GetFromBytes(byte[] bytes) 21 | { 22 | return new ClientIdAppId 23 | { 24 | ClientId = DoubleBytesToInt(bytes[0], bytes[1]), 25 | AppId = bytes[2] 26 | }; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/ClientModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NSmartProxy.Data 5 | { 6 | /// 7 | /// 客户端,包含一个客户端的信息,传输用 8 | /// 9 | public class ClientModel: ByteSerializeableObject 10 | { 11 | public int ClientId; //2 12 | public List AppList; //3 * N 13 | public string IP; //no serialize 14 | public override byte[] ToBytes() 15 | { 16 | byte[] bytes = new byte[2 + AppList.Count * 3]; 17 | byte[] clientIdBytes = IntTo2Bytes(ClientId); 18 | List listBytes = new List(); 19 | listBytes.Add(clientIdBytes[0]); 20 | listBytes.Add(clientIdBytes[1]); 21 | foreach (var app in AppList) 22 | { 23 | listBytes.Add((byte)app.AppId); 24 | listBytes.AddRange(IntTo2Bytes(app.Port)); 25 | } 26 | return listBytes.ToArray(); 27 | } 28 | 29 | public static ClientModel GetFromBytes(byte[] bytes, int totalLength = 0) 30 | { 31 | if (totalLength == 0) 32 | { 33 | totalLength = bytes.Length; 34 | } 35 | ClientModel client = new ClientModel(); 36 | client.ClientId = (bytes[0] << 8) + bytes[1]; 37 | client.AppList = new List(); 38 | int appCount = (totalLength - 2) / 3; 39 | if (((totalLength - 2) % 3) > 0) 40 | { 41 | throw new Exception("格式错误:获取客户端对象失败"); 42 | } 43 | for (int i = 0; i < appCount; i++) 44 | { 45 | App app = new App() 46 | { 47 | AppId = bytes[2 + 3 * i], 48 | Port = (bytes[3 + 3 * i] << 8) + bytes[4 + 3 * i] 49 | }; 50 | client.AppList.Add(app); 51 | } 52 | return client; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/ClientNewAppRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NSmartProxy.Data 4 | { 5 | /// 6 | /// 客户端向服务端申请新app的请求包 7 | /// 8 | public class ClientNewAppRequest : ByteSerializeableObject 9 | { 10 | public int TokenLength; //2 11 | public string Token; //TokenLength 12 | public int ClientId; //2 13 | public int ClientCount; //1 14 | //public string Description;//96 15 | public override byte[] ToBytes() 16 | { 17 | List Allbytes = new List(30); 18 | byte[] bytes1 = System.Text.Encoding.ASCII.GetBytes(Token); 19 | byte[] bytes0 = IntTo2Bytes(bytes1.Length); 20 | byte[] bytes2 = IntTo2Bytes(ClientId); 21 | byte bytes3 = (byte)ClientCount; 22 | //byte[] bytes4 = System.Text.Encoding.UTF8.GetBytes(Description); 23 | Allbytes.AddRange(bytes0); 24 | Allbytes.AddRange(bytes1); 25 | Allbytes.AddRange(bytes2); 26 | Allbytes.Add(bytes3); 27 | //Allbytes.AddRange(bytes4); 28 | return Allbytes.ToArray(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/ClientUserCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.Models 6 | { 7 | public class ClientUserCacheItem 8 | { 9 | //public string ServerEndPoint { get; set; } 10 | public string UserName { get; set; } 11 | //public string UserPwd { get; set; } 12 | public string Token { get; set; } 13 | } 14 | 15 | 16 | /// 17 | /// key服务器名 value用户 18 | /// 19 | public class ClientUserCache : Dictionary 20 | { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/Models/LoginInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data.Models 6 | { 7 | public class LoginInfo 8 | { 9 | public string UserName { get; set; } 10 | public string UserPwd { get; set; } 11 | public string Token { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/NSmartProxy.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/ServerProtocol.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxy.Data 2 | { 3 | public enum ServerProtocol : byte 4 | { 5 | Heartbeat = 0x01, 6 | ClientNewAppRequest = 0x02, 7 | Reconnect = 0x03, 8 | CloseClient = 0x04, 9 | Disconnet = 0x05 10 | } 11 | 12 | /// 13 | /// 反弹控制端口协议头 14 | /// 15 | public enum ControlMethod : byte 16 | { 17 | TCPTransfer = 0x01, 18 | KeepAlive = 0x03, 19 | UDPTransfer = 0x04, 20 | // Control = 0x05, //控制协议,用来让服务端控制客户端的配置 21 | Reconnect = 0x05, //重置协议,服务端发送此信号让客户端重新连接 22 | ForceClose = 0x6, //抢登则强制下线 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/ServerStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data 6 | { 7 | public enum ServerStatus : byte 8 | { 9 | UnknowndFailed = 0x00, 10 | Success = 0x01, 11 | AuthFailed = 0x03, 12 | UserBanned = 0x04 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NSmartProxy.Data/TokenClaims.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Data 6 | { 7 | public class TokenClaims 8 | { 9 | public string UserKey { get; set; } 10 | public DateTime LastTime { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/ConfigHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Dynamic; 3 | using Newtonsoft.Json; 4 | using NSmartProxy.Data; 5 | using System.IO; 6 | 7 | namespace NSmartProxy.Infrastructure 8 | { 9 | public static class ConfigHelper 10 | { 11 | public static string AppSettingFullPath 12 | { 13 | get 14 | { 15 | var processModule = Process.GetCurrentProcess().MainModule; 16 | var path1 =Path.GetDirectoryName(processModule?.FileName) 17 | + Path.DirectorySeparatorChar 18 | + "appsettings.json"; 19 | var path2 = "./appsettings.json"; 20 | if (File.Exists(path1)) 21 | { 22 | return path1; 23 | } 24 | else 25 | { 26 | return path2; 27 | } 28 | } 29 | } 30 | 31 | /// 32 | /// 读配置 33 | /// 34 | /// 35 | public static T ReadAllConfig(string path) 36 | { 37 | using (var fs = new FileStream(path, FileMode.Open)) 38 | { 39 | StreamReader sr = new StreamReader(fs); 40 | var str = sr.ReadToEnd(); 41 | return JsonConvert.DeserializeObject(str); 42 | } 43 | } 44 | 45 | /// 46 | /// 存配置 47 | /// 48 | /// 49 | /// 50 | public static T SaveChanges(this T config, string path) 51 | { 52 | JsonSerializer serializer = new JsonSerializer(); 53 | using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write)) 54 | { 55 | StreamWriter sw = new StreamWriter(fs); 56 | JsonTextWriter jsonWriter = new JsonTextWriter(sw) 57 | { 58 | Formatting = Formatting.Indented, 59 | Indentation = 4, 60 | IndentChar = ' ' 61 | }; 62 | serializer.Serialize(jsonWriter, config); 63 | 64 | sw.Close(); 65 | } 66 | 67 | return config; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/ConsoleHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Security; 5 | using System.Text; 6 | 7 | namespace NSmartProxy.Infrastructure 8 | { 9 | public static class ConsoleHelper 10 | { 11 | public static SecureString ReadPassword(string mask = "*") 12 | { 13 | var password = new SecureString(); 14 | while (true) 15 | { 16 | var i = Console.ReadKey(true); 17 | if (i.Key == ConsoleKey.Enter) 18 | { 19 | Console.WriteLine(); 20 | break; 21 | } 22 | 23 | if (i.Key == ConsoleKey.Backspace) 24 | { 25 | if (password.Length > 0) 26 | { 27 | password.RemoveAt(password.Length - 1); 28 | Console.Write("\b \b"); 29 | } 30 | } 31 | else 32 | { 33 | password.AppendChar(i.KeyChar); 34 | Console.Write(mask); 35 | } 36 | } 37 | password.MakeReadOnly(); 38 | return password; 39 | } 40 | 41 | private static string RestoreSecureString(this SecureString value) 42 | { 43 | var valuePtr = IntPtr.Zero; 44 | try 45 | { 46 | valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value); 47 | return Marshal.PtrToStringUni(valuePtr); 48 | } 49 | finally 50 | { 51 | Marshal.ZeroFreeGlobalAllocUnicode(valuePtr); 52 | } 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/DatetimeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Infrastructure 6 | { 7 | public class DateTimeHelper 8 | { 9 | public static double TimeRange(DateTime From, DateTime To) 10 | { 11 | return (To - From).TotalMilliseconds; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Extensions/AsyncExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace NSmartProxy.Infrastructure 7 | { 8 | public sealed class DisposableScope : IDisposable 9 | { 10 | private readonly Action _closeScopeAction; 11 | public DisposableScope(Action closeScopeAction) 12 | { 13 | _closeScopeAction = closeScopeAction; 14 | } 15 | public void Dispose() 16 | { 17 | _closeScopeAction(); 18 | } 19 | } 20 | 21 | public static class AsyncExtension 22 | { 23 | public static IDisposable CreateTimeoutScope(this IDisposable disposable, TimeSpan timeSpan) 24 | { 25 | var cancellationTokenSource = new CancellationTokenSource(timeSpan); 26 | var cancellationTokenRegistration = cancellationTokenSource.Token.Register(disposable.Dispose); 27 | return new DisposableScope( 28 | () => 29 | { 30 | cancellationTokenRegistration.Dispose(); 31 | cancellationTokenSource.Dispose(); 32 | disposable.Dispose(); 33 | }); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Extensions/HttpServer/HttpServerAttributes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Infrastructure.Extension 6 | { 7 | 8 | /// 9 | /// 返回的是个json 10 | /// 11 | public class APIAttribute : Attribute 12 | { 13 | 14 | } 15 | 16 | /// 17 | /// 返回的是个页面 18 | /// 19 | public class FormAPIAttribute : Attribute 20 | { 21 | 22 | } 23 | 24 | /// 25 | /// 返回的是个文件 26 | /// 27 | public class FileAPIAttribute : Attribute 28 | { 29 | 30 | } 31 | 32 | /// 33 | /// 代表上传文件接口,第一个函数必须是File 34 | /// 35 | public class FileUploadAttribute : Attribute 36 | { 37 | 38 | } 39 | 40 | 41 | /// 42 | /// 代表接口需要校验权限 43 | /// 44 | public class SecureAttribute : Attribute 45 | { 46 | } 47 | 48 | /// 49 | /// 表示一个远程校验类 50 | /// 51 | public class ValidateAPIAttribute : Attribute 52 | { 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/HtmlUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Newtonsoft.Json; 5 | 6 | namespace NSmartProxy 7 | { 8 | public static class HtmlUtil 9 | { 10 | public static byte[] GetContent(string html) 11 | { 12 | return Encoding.UTF8.GetBytes(html.ToString()); 13 | } 14 | 15 | public static string ToJsonString(this object jsonObj) 16 | { 17 | return JsonConvert.SerializeObject(jsonObj); 18 | } 19 | 20 | //GET /welcome 21 | private static bool CompareBytes(byte[] wholeBytes, byte[] partternWord) 22 | { 23 | for (int i = 0; i < partternWord.Length; i++) 24 | { 25 | if (wholeBytes[i] != partternWord[i]) 26 | { 27 | return false; 28 | } 29 | } 30 | return true; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/I18N.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Text; 6 | 7 | namespace NSmartProxy.Infrastructure 8 | { 9 | public class I18N 10 | { 11 | private const string BASE_PATH = "i18n"; 12 | private static string originFullPath; 13 | private static string lFullPath; 14 | public static Dictionary LMap; 15 | public static string L(string lStr) 16 | { 17 | if (LMap.ContainsKey(lStr)) 18 | { 19 | return LMap[lStr]; 20 | } 21 | else 22 | { 23 | LMap.Add(lStr, lStr); 24 | File.AppendAllLines(originFullPath, new string[] { lStr }); 25 | return lStr; 26 | } 27 | } 28 | 29 | static I18N() 30 | { 31 | 32 | LMap = new Dictionary(); 33 | string originLFile = "ol.txt"; 34 | //debug模式,提取代码中的多语言字段 35 | string entryPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\" + BASE_PATH + "\\"; 36 | string langSign = System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag.ToLowerInvariant(); 37 | originFullPath = entryPath + originLFile; 38 | 39 | 40 | if (langSign.StartsWith("zh")) 41 | { 42 | lFullPath = entryPath + "zh.txt"; 43 | } 44 | else 45 | { 46 | lFullPath = entryPath + "en.txt"; 47 | } 48 | 49 | if (!Directory.Exists(entryPath)) 50 | { 51 | Directory.CreateDirectory(entryPath); 52 | } 53 | if (!File.Exists(originFullPath)) 54 | { 55 | File.Create(originFullPath).Close(); 56 | } 57 | if (!File.Exists(lFullPath)) 58 | { 59 | File.Create(lFullPath).Close(); 60 | } 61 | 62 | //读取所有多语言文件 TODO 先暂时只读取原始文件 63 | var lstrs = File.ReadAllLines(lFullPath); 64 | var ostrs = File.ReadAllLines(originFullPath); 65 | for (var i = 0; i < ostrs.Length; i++) 66 | { 67 | if (i > lstrs.Length - 1) 68 | { 69 | LMap[ostrs[i]] = ostrs[i]; 70 | File.AppendAllLines(lFullPath, new string[] { ostrs[i] });//补齐多的行 71 | } 72 | else 73 | { 74 | LMap[ostrs[i]] = lstrs[i]; 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Interfaces/IHttpServerContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.Infrastructure.Interfaces 6 | { 7 | public interface IServerContext 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Interfaces/ILogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace NSmartProxy.Interfaces 5 | { 6 | public interface INSmartLogger 7 | { 8 | void Debug(object message); 9 | 10 | void Error(object message,Exception ex); 11 | 12 | void Info(object message); 13 | } 14 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Interfaces/IWebController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Infrastructure.Interfaces 7 | { 8 | public interface IWebController 9 | { 10 | void SetContext(HttpListenerContext context); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/BaseChannel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LiteNetLib 4 | { 5 | internal abstract class BaseChannel 6 | { 7 | public BaseChannel Next; 8 | protected readonly NetPeer Peer; 9 | protected readonly Queue OutgoingQueue; 10 | 11 | protected BaseChannel(NetPeer peer) 12 | { 13 | Peer = peer; 14 | OutgoingQueue = new Queue(64); 15 | } 16 | 17 | public int PacketsInQueue 18 | { 19 | get { return OutgoingQueue.Count; } 20 | } 21 | 22 | public void AddToQueue(NetPacket packet) 23 | { 24 | lock (OutgoingQueue) 25 | OutgoingQueue.Enqueue(packet); 26 | } 27 | 28 | public abstract void SendNextPackets(); 29 | public abstract bool ProcessPacket(NetPacket packet); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/ConnectionRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Threading; 3 | using LiteNetLib.Utils; 4 | 5 | namespace LiteNetLib 6 | { 7 | public enum ConnectionRequestType 8 | { 9 | Incoming, 10 | PeerToPeer 11 | } 12 | 13 | internal enum ConnectionRequestResult 14 | { 15 | None, 16 | Accept, 17 | Reject 18 | } 19 | 20 | internal interface IConnectionRequestListener 21 | { 22 | void OnConnectionSolved(ConnectionRequest request, byte[] rejectData, int start, int length); 23 | } 24 | 25 | public class ConnectionRequest 26 | { 27 | private readonly IConnectionRequestListener _listener; 28 | private int _used; 29 | 30 | public IPEndPoint RemoteEndPoint { get { return Peer.EndPoint; } } 31 | public readonly NetDataReader Data; 32 | public ConnectionRequestType Type { get; private set; } 33 | 34 | internal ConnectionRequestResult Result { get; private set; } 35 | internal readonly long ConnectionId; 36 | internal readonly byte ConnectionNumber; 37 | internal readonly NetPeer Peer; 38 | 39 | //类似悲观锁定?? 40 | private bool TryActivate() 41 | { 42 | return Interlocked.CompareExchange(ref _used, 1, 0) == 0; 43 | } 44 | 45 | internal ConnectionRequest( 46 | long connectionId, 47 | byte connectionNumber, 48 | ConnectionRequestType type, 49 | NetDataReader netDataReader, 50 | NetPeer peer, 51 | IConnectionRequestListener listener) 52 | { 53 | ConnectionId = connectionId; 54 | ConnectionNumber = connectionNumber; 55 | Type = type; 56 | Peer = peer; 57 | Data = netDataReader; 58 | _listener = listener; 59 | } 60 | 61 | public NetPeer AcceptIfKey(string key) 62 | { 63 | if (!TryActivate()) 64 | return null; 65 | try 66 | { 67 | if (Data.GetString() == key) 68 | { 69 | Result = ConnectionRequestResult.Accept; 70 | _listener.OnConnectionSolved(this, null, 0, 0); 71 | return Peer; 72 | } 73 | } 74 | catch 75 | { 76 | NetDebug.WriteError("[AC] Invalid incoming data"); 77 | } 78 | Result = ConnectionRequestResult.Reject; 79 | _listener.OnConnectionSolved(this, null, 0, 0); 80 | return null; 81 | } 82 | 83 | /// 84 | /// Accept connection and get new NetPeer as result 85 | /// 86 | /// Connected NetPeer 87 | public NetPeer Accept() 88 | { 89 | if (!TryActivate()) 90 | return null; 91 | Result = ConnectionRequestResult.Accept; 92 | _listener.OnConnectionSolved(this, null, 0, 0); 93 | return Peer; 94 | } 95 | 96 | public void Reject(byte[] rejectData, int start, int length) 97 | { 98 | if (!TryActivate()) 99 | return; 100 | Result = ConnectionRequestResult.Reject; 101 | _listener.OnConnectionSolved(this, rejectData, start, length); 102 | } 103 | 104 | public void Reject() 105 | { 106 | Reject(null, 0, 0); 107 | } 108 | 109 | public void Reject(byte[] rejectData) 110 | { 111 | Reject(rejectData, 0, rejectData.Length); 112 | } 113 | 114 | public void Reject(NetDataWriter rejectData) 115 | { 116 | Reject(rejectData.Data, 0, rejectData.Length); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/INetEventListener.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/INetEventListener.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/Layers/Crc32cLayer.cs: -------------------------------------------------------------------------------- 1 | using LiteNetLib.Utils; 2 | using System; 3 | 4 | namespace LiteNetLib.Layers 5 | { 6 | public sealed class Crc32cLayer : PacketLayerBase 7 | { 8 | public Crc32cLayer() : base(CRC32C.ChecksumSize) 9 | { 10 | 11 | } 12 | 13 | public override void ProcessInboundPacket(ref byte[] data, ref int length) 14 | { 15 | if (length < NetConstants.HeaderSize + CRC32C.ChecksumSize) 16 | { 17 | NetDebug.WriteError("[NM] DataReceived size: bad!"); 18 | return; 19 | } 20 | 21 | int checksumPoint = length - CRC32C.ChecksumSize; 22 | if (CRC32C.Compute(data, 0, checksumPoint) != BitConverter.ToUInt32(data, checksumPoint)) 23 | { 24 | NetDebug.Write("[NM] DataReceived checksum: bad!"); 25 | return; 26 | } 27 | length -= CRC32C.ChecksumSize; 28 | } 29 | 30 | public override void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length) 31 | { 32 | FastBitConverter.GetBytes(data, length, CRC32C.Compute(data, offset, length)); 33 | length += CRC32C.ChecksumSize; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/Layers/PacketLayerBase.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib.Layers 2 | { 3 | public abstract class PacketLayerBase 4 | { 5 | public readonly int ExtraPacketSizeForLayer; 6 | 7 | protected PacketLayerBase(int extraPacketSizeForLayer) 8 | { 9 | ExtraPacketSizeForLayer = extraPacketSizeForLayer; 10 | } 11 | 12 | public abstract void ProcessInboundPacket(ref byte[] data, ref int length); 13 | public abstract void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/Layers/XorEncryptLayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace LiteNetLib.Layers 5 | { 6 | public class XorEncryptLayer : PacketLayerBase 7 | { 8 | private byte[] _byteKey; 9 | 10 | public XorEncryptLayer() : base(0) 11 | { 12 | 13 | } 14 | 15 | public XorEncryptLayer(byte[] key) : this() 16 | { 17 | SetKey(key); 18 | } 19 | 20 | public XorEncryptLayer(string key) : this() 21 | { 22 | SetKey(key); 23 | } 24 | 25 | public void SetKey(string key) 26 | { 27 | _byteKey = Encoding.UTF8.GetBytes(key); 28 | } 29 | 30 | public void SetKey(byte[] key) 31 | { 32 | if (_byteKey == null || _byteKey.Length != key.Length) 33 | _byteKey = new byte[key.Length]; 34 | Buffer.BlockCopy(key, 0, _byteKey, 0, key.Length); 35 | } 36 | 37 | public override void ProcessInboundPacket(ref byte[] data, ref int length) 38 | { 39 | if (_byteKey == null) 40 | return; 41 | for (var i = 0; i < length; i++) 42 | { 43 | var offset = i % _byteKey.Length; 44 | data[i] = (byte)(data[i] ^ _byteKey[offset]); 45 | } 46 | } 47 | 48 | public override void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length) 49 | { 50 | if (_byteKey == null) 51 | return; 52 | var cur = offset; 53 | for (var i = 0; i < length; i++, cur++) 54 | { 55 | data[cur] = (byte)(data[cur] ^ _byteKey[i % _byteKey.Length]); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NatPunchModule.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/NatPunchModule.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetConstants.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib 2 | { 3 | /// 4 | /// Sending method type 5 | /// 6 | public enum DeliveryMethod : byte 7 | { 8 | /// 9 | /// Unreliable. Packets can be dropped, can be duplicated, can arrive without order. 10 | /// 11 | Unreliable = 4, 12 | 13 | /// 14 | /// Reliable. Packets won't be dropped, won't be duplicated, can arrive without order. 15 | /// 16 | ReliableUnordered = 0, 17 | 18 | /// 19 | /// Unreliable. Packets can be dropped, won't be duplicated, will arrive in order. 20 | /// 21 | Sequenced = 1, 22 | 23 | /// 24 | /// Reliable and ordered. Packets won't be dropped, won't be duplicated, will arrive in order. 25 | /// 26 | ReliableOrdered = 2, 27 | 28 | /// 29 | /// Reliable only last packet. Packets can be dropped (except the last one), won't be duplicated, will arrive in order. 30 | /// 31 | ReliableSequenced = 3 32 | } 33 | 34 | /// 35 | /// 常量,在实际情况可以调校这些常量. 36 | /// 37 | public static class NetConstants 38 | { 39 | //can be tuned 40 | public const int DefaultWindowSize = 64; 41 | public const int SocketBufferSize = 1024 * 1024; //1mb 42 | public const int SocketTTL = 255; 43 | 44 | public const int HeaderSize = 1; 45 | public const int ChanneledHeaderSize = 4; 46 | public const int FragmentHeaderSize = 6; 47 | public const int FragmentTotalSize = ChanneledHeaderSize + FragmentHeaderSize; 48 | public const ushort MaxSequence = 32768; 49 | public const ushort HalfMaxSequence = MaxSequence / 2; 50 | 51 | //protocol 52 | internal const int ProtocolId = 10; 53 | internal const int MaxUdpHeaderSize = 68; 54 | 55 | internal static readonly int[] PossibleMtu = 56 | { 57 | 576 - MaxUdpHeaderSize, //minimal 58 | 1232 - MaxUdpHeaderSize, 59 | 1460 - MaxUdpHeaderSize, //google cloud 60 | 1472 - MaxUdpHeaderSize, //VPN 61 | 1492 - MaxUdpHeaderSize, //Ethernet with LLC and SNAP, PPPoE (RFC 1042) 62 | 1500 - MaxUdpHeaderSize //Ethernet II (RFC 1191) 63 | }; 64 | 65 | internal static readonly int MaxPacketSize = PossibleMtu[PossibleMtu.Length - 1]; 66 | 67 | //peer specific 68 | public const byte MaxConnectionNumber = 4; 69 | 70 | public const int PacketPoolSize = 1000; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetDebug.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace LiteNetLib 5 | { 6 | public enum NetLogLevel 7 | { 8 | Warning, 9 | Error, 10 | Trace, 11 | Info 12 | } 13 | 14 | /// 15 | /// Interface to implement for your own logger 16 | /// 17 | public interface INetLogger 18 | { 19 | void WriteNet(NetLogLevel level, string str, params object[] args); 20 | } 21 | 22 | /// 23 | /// Static class for defining your own LiteNetLib logger instead of Console.WriteLine 24 | /// or Debug.Log if compiled with UNITY flag 25 | /// 26 | public static class NetDebug 27 | { 28 | public static INetLogger Logger = null; 29 | private static readonly object DebugLogLock = new object(); 30 | private static void WriteLogic(NetLogLevel logLevel, string str, params object[] args) 31 | { 32 | lock (DebugLogLock) 33 | { 34 | if (Logger == null) 35 | { 36 | #if UNITY_4 || UNITY_5 || UNITY_5_3_OR_NEWER 37 | UnityEngine.Debug.Log(string.Format(str, args)); 38 | #else 39 | Console.WriteLine(str, args); 40 | #endif 41 | } 42 | else 43 | { 44 | Logger.WriteNet(logLevel, str, args); 45 | } 46 | } 47 | } 48 | 49 | [Conditional("DEBUG")] 50 | internal static void Write(string str, params object[] args) 51 | { 52 | WriteLogic(NetLogLevel.Trace, str, args); 53 | } 54 | 55 | [Conditional("DEBUG")] 56 | internal static void Write(NetLogLevel level, string str, params object[] args) 57 | { 58 | WriteLogic(level, str, args); 59 | } 60 | 61 | [Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")] 62 | internal static void WriteForce(string str, params object[] args) 63 | { 64 | WriteLogic(NetLogLevel.Trace, str, args); 65 | } 66 | 67 | [Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")] 68 | internal static void WriteForce(NetLogLevel level, string str, params object[] args) 69 | { 70 | WriteLogic(level, str, args); 71 | } 72 | 73 | internal static void WriteError(string str, params object[] args) 74 | { 75 | WriteLogic(NetLogLevel.Error, str, args); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetExceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace LiteNetLib 3 | { 4 | public class InvalidPacketException: ArgumentException 5 | { 6 | public InvalidPacketException() 7 | { 8 | } 9 | 10 | public InvalidPacketException(string message): base(message) 11 | { 12 | } 13 | 14 | public InvalidPacketException(string message, Exception innerException): base(message, innerException) 15 | { 16 | } 17 | } 18 | 19 | public class TooBigPacketException : InvalidPacketException 20 | { 21 | public TooBigPacketException() 22 | { 23 | } 24 | 25 | public TooBigPacketException(string message) : base(message) 26 | { 27 | } 28 | 29 | public TooBigPacketException(string message, Exception innerException) : base(message, innerException) 30 | { 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetManager.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/NetManager.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetPacket.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/NetPacket.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetPacketPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace LiteNetLib 5 | { 6 | internal sealed class NetPacketPool 7 | { 8 | private readonly NetPacket[] _pool = new NetPacket[NetConstants.PacketPoolSize]; 9 | 10 | private int _count; 11 | 12 | public NetPacket GetWithData(PacketProperty property, byte[] data, int start, int length) 13 | { 14 | var packet = GetWithProperty(property, length); 15 | Buffer.BlockCopy(data, start, packet.RawData, NetPacket.GetHeaderSize(property), length); 16 | return packet; 17 | } 18 | 19 | private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 20 | //这种精度的锁技术 有待研究 21 | public NetPacket GetPacket(int size, bool clear) 22 | { 23 | NetPacket packet = null; 24 | if (size <= NetConstants.MaxPacketSize) 25 | { 26 | _lock.EnterUpgradeableReadLock(); 27 | if (_count > 0) 28 | { 29 | _lock.EnterWriteLock(); 30 | _count--; 31 | packet = _pool[_count]; 32 | _pool[_count] = null; 33 | _lock.ExitWriteLock(); 34 | } 35 | _lock.ExitUpgradeableReadLock(); 36 | } 37 | if (packet == null) 38 | { 39 | //allocate new packet 40 | packet = new NetPacket(size); 41 | } 42 | else 43 | { 44 | //reallocate packet data if packet not fits 45 | packet.Realloc(size, clear); 46 | } 47 | return packet; 48 | } 49 | 50 | //Get packet with size 51 | public NetPacket GetWithProperty(PacketProperty property, int size) 52 | { 53 | size += NetPacket.GetHeaderSize(property); 54 | NetPacket packet = GetPacket(size, true); 55 | packet.Property = property; 56 | return packet; 57 | } 58 | 59 | public void Recycle(NetPacket packet) 60 | { 61 | if (packet.RawData.Length > NetConstants.MaxPacketSize) 62 | { 63 | //Dont pool big packets. Save memory 64 | return; 65 | } 66 | 67 | //Clean fragmented flag 68 | packet.RawData[0] = 0; 69 | 70 | _lock.EnterUpgradeableReadLock(); 71 | if (_count == NetConstants.PacketPoolSize) 72 | { 73 | _lock.ExitUpgradeableReadLock(); 74 | return; 75 | } 76 | _lock.EnterWriteLock(); 77 | _pool[_count] = packet; 78 | _count++; 79 | _lock.ExitWriteLock(); 80 | _lock.ExitUpgradeableReadLock(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetPeer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/NetPeer.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetSocket.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/NetSocket.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetStatistics.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib 2 | { 3 | public sealed class NetStatistics 4 | { 5 | public ulong PacketsSent; 6 | public ulong PacketsReceived; 7 | public ulong BytesSent; 8 | public ulong BytesReceived; 9 | public ulong PacketLoss; 10 | public ulong PacketLossPercent 11 | { 12 | get { return PacketsSent == 0 ? 0 : PacketLoss * 100 / PacketsSent; } 13 | } 14 | 15 | public ulong SequencedPacketLoss; 16 | 17 | public void Reset() 18 | { 19 | PacketsSent = 0; 20 | PacketsReceived = 0; 21 | BytesSent = 0; 22 | BytesReceived = 0; 23 | PacketLoss = 0; 24 | } 25 | 26 | public override string ToString() 27 | { 28 | return 29 | string.Format( 30 | "BytesReceived: {0}\nPacketsReceived: {1}\nBytesSent: {2}\nPacketsSent: {3}\nPacketLoss: {4}\nPacketLossPercent: {5}\n", 31 | BytesReceived, 32 | PacketsReceived, 33 | BytesSent, 34 | PacketsSent, 35 | PacketLoss, 36 | PacketLossPercent); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/NetUtils.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy.Infrastructure/LiteNetLib/NetUtils.cs -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/SequencedChannel.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib 2 | { 3 | internal sealed class SequencedChannel : BaseChannel 4 | { 5 | private int _localSequence; 6 | private ushort _remoteSequence; 7 | private readonly bool _reliable; 8 | private NetPacket _lastPacket; 9 | private readonly NetPacket _ackPacket; 10 | private bool _mustSendAck; 11 | private readonly byte _id; 12 | 13 | public SequencedChannel(NetPeer peer, bool reliable, byte id) : base(peer) 14 | { 15 | _id = id; 16 | _reliable = reliable; 17 | if (_reliable) 18 | _ackPacket = new NetPacket(PacketProperty.Ack, 0) {ChannelId = id}; 19 | } 20 | 21 | public override void SendNextPackets() 22 | { 23 | if (_reliable && OutgoingQueue.Count == 0) 24 | { 25 | var packet = _lastPacket; 26 | if(packet != null) 27 | Peer.SendUserData(packet); 28 | } 29 | else 30 | { 31 | lock (OutgoingQueue) 32 | { 33 | while (OutgoingQueue.Count > 0) 34 | { 35 | NetPacket packet = OutgoingQueue.Dequeue(); 36 | _localSequence = (_localSequence + 1) % NetConstants.MaxSequence; 37 | packet.Sequence = (ushort)_localSequence; 38 | packet.ChannelId = _id; 39 | Peer.SendUserData(packet); 40 | 41 | if (_reliable && OutgoingQueue.Count == 0) 42 | _lastPacket = packet; 43 | else 44 | Peer.NetManager.NetPacketPool.Recycle(packet); 45 | } 46 | } 47 | } 48 | 49 | if (_reliable && _mustSendAck) 50 | { 51 | _mustSendAck = false; 52 | _ackPacket.Sequence = _remoteSequence; 53 | Peer.SendUserData(_ackPacket); 54 | } 55 | } 56 | 57 | public override bool ProcessPacket(NetPacket packet) 58 | { 59 | if (packet.Property == PacketProperty.Ack) 60 | { 61 | if (_reliable && _lastPacket != null && packet.Sequence == _lastPacket.Sequence) 62 | _lastPacket = null; 63 | return false; 64 | } 65 | int relative = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence); 66 | bool packetProcessed = false; 67 | if (packet.Sequence < NetConstants.MaxSequence && relative > 0) 68 | { 69 | Peer.Statistics.PacketLoss += (ulong)(relative - 1); 70 | _remoteSequence = packet.Sequence; 71 | Peer.AddIncomingPacket(packet); 72 | packetProcessed = true; 73 | } 74 | _mustSendAck = true; 75 | return packetProcessed; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/SimpleChannel.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib 2 | { 3 | internal sealed class SimpleChannel : BaseChannel 4 | { 5 | public SimpleChannel(NetPeer peer) : base(peer) 6 | { 7 | 8 | } 9 | 10 | public override void SendNextPackets() 11 | { 12 | lock (OutgoingQueue) 13 | { 14 | while (OutgoingQueue.Count > 0) 15 | { 16 | NetPacket packet = OutgoingQueue.Dequeue(); 17 | Peer.SendUserData(packet); 18 | Peer.NetManager.NetPacketPool.Recycle(packet); 19 | } 20 | } 21 | } 22 | 23 | public override bool ProcessPacket(NetPacket packet) 24 | { 25 | return false; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/LiteNetLib/Utils/INetSerializable.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib.Utils 2 | { 3 | public interface INetSerializable 4 | { 5 | void Serialize(NetDataWriter writer); 6 | void Deserialize(NetDataReader reader); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/NSmartProxy.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;net6.0 5 | True 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | TextTemplatingFileGenerator 21 | NSPVersion.cs 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | True 32 | True 33 | NSPVersion.tt 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Shared/Global.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy.Interfaces; 2 | 3 | namespace NSmartProxy.Shared 4 | { 5 | /// 6 | /// 放一些全局公用的静态变量 7 | /// 8 | public sealed class Global 9 | { 10 | public const string NO_TOKEN_STRING = "notoken"; 11 | 12 | public const string TOKEN_COOKIE_NAME = "NSPTK"; 13 | //public const string NSmartProxyClientName = "NSmartProxy Client v1.1.1028"; 14 | //public const string NSmartProxyServerName = "NSmartProxy Server v1.1.1028"; 15 | 16 | public const int ClientReconnectInterval = 3000;//客户端断线重连时间间隔(毫秒) 17 | 18 | public const int HeartbeatInterval = 30000; //心跳间隔(毫秒) 19 | public const int HeartbeatCheckInterval = 90000; //心跳检测间隔(毫秒) 20 | public const int DefaultConnectTimeout = 30000; //默认连接超时时间(毫秒) 21 | public const int DefaultWriteAckTimeout = 10000;//调用具备ack确认协议的等待时间(毫秒) 22 | public const int DefaultPopClientTimeout = 30000; //反弹连接超时时间(毫秒) 23 | public const int TokenExpiredMinutes = 60 * 24 * 30; //token过期时间(分钟)TODO 待生效 24 | 25 | public const string NSPClientServiceDisplayName = "NSPClient";//windows服务显示名 26 | public const string NSPClientServiceName = "NSPClient";//windows服务名 27 | 28 | public const int ClientUdpReceiveTimeout = 3000;//客户端udp接收超时时长(毫秒) 29 | 30 | public const int ClientTunnelBufferSize = 1024 * 1024 * 1024; //客户端数据包大小 31 | public const int ClientUdpBufferSize = 65535;//服务端udp数据包大小 32 | #region 服务端配置 33 | 34 | public const int StartArrangedPort = 20000; 35 | public const string NSPServerDisplayName = "NSPServer";//windows服务显示名 36 | public const string NSPServerServiceName = "NSPServer";//windows服务名 37 | 38 | public const int ServerTunnelBufferSize = 1024 * 1024 * 1024;//服务端数据包大小 39 | public const int ServerUdpBufferSize = 65535;//服务端udp数据包大小 40 | 41 | 42 | public static INSmartLogger Logger; 43 | #endregion 44 | } 45 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Shared/IDbOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NSmartProxy.Database 5 | { 6 | public interface IDbOperator : IDisposable 7 | { 8 | IDbOperator Open(); 9 | void Insert(long key, string value); 10 | void Insert(string key, string value); 11 | void Update(long key, string value); 12 | void UpdateByName(string userName,string newUserName, string value); 13 | List Select(int startIndex, int length); 14 | string GetConfig(string userId); 15 | void SetConfig(string userId,string config); 16 | string Get(long key); 17 | string Get(string key); 18 | void Delete(int index); 19 | void DeleteHash(string key); 20 | long GetLength(); 21 | void Close(); 22 | bool Exist(string key); 23 | int GetCount(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Shared/NSPVersion.cs: -------------------------------------------------------------------------------- 1 |  2 | public sealed class NSPVersion 3 | { 4 | public const string NO_TOKEN_STRING = "notoken"; 5 | public const string NSmartProxyClientName = "NSmartProxy Client v1.4.8596.1967"; 6 | public const string NSmartProxyServerName = "NSmartProxy Server v1.4.8596.1967"; 7 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Shared/NSPVersion.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <# 7 | var v1 = DateTime.Now.Ticks.ToString().Substring(2, 4).TrimStart('0'); 8 | var v2 = DateTime.Now.Ticks.ToString().Substring(6, 4).TrimStart('0'); 9 | #> 10 | 11 | public sealed class NSPVersion 12 | { 13 | public const string NO_TOKEN_STRING = "notoken"; 14 | public const string NSmartProxyClientName = "NSmartProxy Client v1.4.<#=v1#>.<#=v2#>"; 15 | public const string NSmartProxyServerName = "NSmartProxy Server v1.4.<#=v1#>.<#=v2#>"; 16 | } -------------------------------------------------------------------------------- /src/NSmartProxy.Infrastructure/Snappy/Snappy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.IO; 4 | 5 | namespace Snappy.Sharp 6 | { 7 | public static class Snappy 8 | { 9 | internal const int LITERAL = 0; 10 | internal const int COPY_1_BYTE_OFFSET = 1; // 3 bit length + 3 bits of offset in opcode 11 | internal const int COPY_2_BYTE_OFFSET = 2; 12 | internal const int COPY_4_BYTE_OFFSET = 3; 13 | 14 | public static int MaxCompressedLength(int sourceLength) 15 | { 16 | var compressor = new SnappyCompressor(); 17 | return compressor.MaxCompressedLength(sourceLength); 18 | } 19 | 20 | public static byte[] Compress(byte[] uncompressed) 21 | { 22 | var target = new SnappyCompressor(); 23 | var result = new byte[target.MaxCompressedLength(uncompressed.Length)]; 24 | var count = target.Compress(uncompressed, 0, uncompressed.Length, result); 25 | return result.Take(count).ToArray(); 26 | } 27 | 28 | public static void Compress(Stream uncompressed, SnappyStream compressed) 29 | { 30 | throw new NotImplementedException(); 31 | } 32 | 33 | public static int GetUncompressedLength(byte[] compressed, int offset = 0) 34 | { 35 | var decompressor = new SnappyDecompressor(); 36 | return decompressor.ReadUncompressedLength(compressed, offset)[0]; 37 | } 38 | 39 | public static byte[] Uncompress(byte[] compressed) 40 | { 41 | throw new NotImplementedException(); 42 | } 43 | 44 | public static void Uncompress(SnappyStream compressed, StreamWriter uncompressed) 45 | { 46 | throw new NotImplementedException(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NSmartProxy.NUnitTest/CAGenerate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Security; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Text; 7 | using NSmartProxy.Extension; 8 | using NUnit.Framework; 9 | using NUnit.Framework.Internal; 10 | 11 | namespace NSmartProxy.NUnitTest 12 | { 13 | public class CAGenerate 14 | { 15 | 16 | [SetUp] 17 | public void Setup() 18 | { 19 | } 20 | [Test] 21 | public void TestCAGen() 22 | { 23 | 24 | var ca = CAGen.GenerateCA("shao"); 25 | var export = ca.Export(X509ContentType.Pfx); 26 | File.WriteAllBytes("c:\\test.pfx", export); 27 | Assert.NotNull(ca); 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NSmartProxy.NUnitTest/HttpAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using NSmartProxy; 4 | using NUnit.Framework; 5 | 6 | namespace Tests 7 | { 8 | public class Tests 9 | { 10 | [SetUp] 11 | public void Setup() 12 | { 13 | } 14 | 15 | [Test] 16 | public void Test1() 17 | { 18 | Assert.Pass(); 19 | } 20 | 21 | [Test] 22 | public void TestTail() 23 | { 24 | var strs = GetLogFileInfo(3); 25 | Assert.LessOrEqual(strs.Length, 3); 26 | 27 | } 28 | 29 | private string[] GetLogFileInfo(int lastLines) 30 | { 31 | string baseLogPath = "D:\\3000git\\NSmartProxy\\src\\NSmartProxy.ServerHost\\bin\\Debug\\netcoreapp2.2\\log"; 32 | DirectoryInfo dir = new DirectoryInfo(baseLogPath); 33 | FileInfo[] files = dir.GetFiles("*.log*"); 34 | DateTime recentWrite = DateTime.MinValue; 35 | FileInfo recentFile = null; 36 | 37 | foreach (FileInfo file in files) 38 | { 39 | if (file.LastWriteTime > recentWrite) 40 | { 41 | recentWrite = file.LastWriteTime; 42 | recentFile = file; 43 | } 44 | } 45 | 46 | using (var fs = File.OpenRead(recentFile.FullName)) 47 | { 48 | var sr = new StreamReader(fs); 49 | return sr.Tail(lastLines); 50 | } 51 | } 52 | 53 | 54 | 55 | } 56 | } -------------------------------------------------------------------------------- /src/NSmartProxy.NUnitTest/NSmartProxy.NUnitTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/NSmartProxy.NUnitTest/P2PPunch.cs: -------------------------------------------------------------------------------- 1 | using LiteNetLib; 2 | using LiteNetLib.Utils; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | namespace NSmartProxy.NUnitTest 9 | { 10 | class P2PPunch 11 | { 12 | 13 | public void Server() 14 | { 15 | EventBasedNetListener listener = new EventBasedNetListener(); 16 | NetManager server = new NetManager(listener); 17 | server.Start(9050 /* port */); 18 | 19 | listener.ConnectionRequestEvent += request => 20 | { 21 | //if (server.ConnectedPeersCount < 10 /* max connections */) 22 | // request.AcceptIfKey("SomeConnectionKey"); 23 | //else 24 | // request.Reject(); 25 | }; 26 | 27 | listener.PeerConnectedEvent += peer => 28 | { 29 | Console.WriteLine("We got connection: {0}", peer.EndPoint); // Show peer ip 30 | NetDataWriter writer = new NetDataWriter(); // Create writer class 31 | writer.Put("Hello client!"); // Put some string 32 | peer.Send(writer, DeliveryMethod.ReliableOrdered); // Send with reliability 33 | }; 34 | 35 | while (!Console.KeyAvailable) 36 | { 37 | server.PollEvents(); 38 | Thread.Sleep(15); 39 | } 40 | 41 | server.Stop(); 42 | } 43 | 44 | public void Client() 45 | { 46 | EventBasedNetListener listener = new EventBasedNetListener(); 47 | NetManager client = new NetManager(listener); 48 | client.Start(); 49 | client.Connect("localhost" /* host ip or name */, 9050 /* port */, "SomeConnectionKey" /* text key or NetDataWriter */); 50 | listener.NetworkReceiveEvent += (fromPeer, dataReader, deliveryMethod) => 51 | { 52 | Console.WriteLine("We got: {0}", dataReader.GetString(100 /* max length of string */)); 53 | dataReader.Recycle(); 54 | }; 55 | 56 | while (!Console.KeyAvailable) 57 | { 58 | client.PollEvents(); 59 | Thread.Sleep(15); 60 | } 61 | 62 | client.Stop(); 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /src/NSmartProxy.P2PClient46/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/NSmartProxy.P2PClient46/NSmartProxy.P2PClient46.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {DA8FC4D6-FC4E-4761-B337-F2AD166B07B3} 8 | Exe 9 | NSmartProxy.P2PClient46 10 | NSmartProxy.P2PClient46 11 | v4.6.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {8604f141-1392-434c-af51-a1b73b214d98} 55 | NSmartProxy.Infrastructure 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/NSmartProxy.P2PClient46/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("NSmartProxy.P2PClient46")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NSmartProxy.P2PClient46")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("da8fc4d6-fc4e-4761-b337-f2ad166b07b3")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/NSmartProxy.P2PHost46/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/NSmartProxy.P2PHost46/NSmartProxy.P2PHost46.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {422507C5-3C57-4526-A028-8C2E5B213813} 8 | Exe 9 | NSmartProxy.P2PClient46 10 | NSmartProxy.P2PClient46 11 | v4.6.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {8604f141-1392-434c-af51-a1b73b214d98} 55 | NSmartProxy.Infrastructure 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/NSmartProxy.P2PHost46/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("NSmartProxy.P2PClient46")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NSmartProxy.P2PClient46")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("da8fc4d6-fc4e-4761-b337-f2ad166b07b3")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/NSmartProxy.ServerHost/Dockerfile: -------------------------------------------------------------------------------- 1 | #FROM microsoft/dotnet:2.2-sdk AS build 2 | #WORKDIR /app 3 | # 4 | ## copy csproj and restore as distinct layers 5 | #COPY *.csproj ./ 6 | #RUN dotnet restore 7 | # 8 | ## copy everything else and build app 9 | #COPY . ./ 10 | #RUN dotnet publish -c Release -o out 11 | # 12 | #FROM microsoft/dotnet:2.2-aspnetcore-runtime AS runtime 13 | #WORKDIR /app 14 | #COPY --from=build /app/out ./ 15 | #EXPOSE 12300-22300 16 | #ENTRYPOINT ["dotnet", "NSmartProxy.ServerHost.dll"] 17 | 18 | #need combile 1st. 19 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS runtime 20 | WORKDIR /app 21 | COPY / /app/ 22 | EXPOSE 12300-22300 23 | ENTRYPOINT ["dotnet", "NSmartProxy.ServerHost.dll"] -------------------------------------------------------------------------------- /src/NSmartProxy.ServerHost/NSmartProxy.ServerHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Always 32 | Always 33 | true 34 | 35 | 36 | PreserveNewest 37 | 38 | 39 | 40 | 7.1 41 | ../../test/build/nspserver 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/NSmartProxy.ServerHost/Program.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy.Shared; 2 | using PeterKottas.DotNetCore.WindowsService; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace NSmartProxy.ServerHost 9 | { 10 | public class Program 11 | { 12 | static void Main() 13 | { 14 | //wait 15 | ServiceRunner.Run(config => 16 | { 17 | var name = Global.NSPServerServiceName; 18 | config.SetDisplayName(Global.NSPServerServiceName); 19 | config.SetName(Global.NSPServerDisplayName); 20 | config.SetDescription(NSPVersion.NSmartProxyServerName); 21 | 22 | config.Service(serviceConfig => 23 | { 24 | serviceConfig.ServiceFactory((extraArguments, controller) => 25 | { 26 | return new ServerHost(); 27 | }); 28 | 29 | serviceConfig.OnStart((service, extraParams) => 30 | { 31 | Console.WriteLine("Service {0} started", name); 32 | Task.Run(() => service.Start()); 33 | }); 34 | 35 | serviceConfig.OnStop(service => 36 | { 37 | Console.WriteLine("Service {0} stopped", name); 38 | Task.Run(() => service.Stop()); 39 | }); 40 | 41 | serviceConfig.OnError(e => 42 | { 43 | Console.WriteLine("Service {0} errored with exception : {1}", name, e.Message); 44 | }); 45 | }); 46 | 47 | 48 | }); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/NSmartProxy.ServerHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ReversePort": 7842, //反向连接端口 3 | "ConfigPort": 7841, //配置服务端口 4 | "WebAPIPort": 12309, //API服务端口 5 | "ReversePort_Out": 0, //对外端口,如果服务端存在端口转换需要配置此项,为0或者不配默认用内网端口 6 | "ConfigPort_Out": 0 //对外端口,如果服务端存在端口转换需要配置此项,为0或者不配默认用内网端口 7 | } -------------------------------------------------------------------------------- /src/NSmartProxy.ServerHost/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/NSmartProxy/Database/SequenceFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace NSmartProxy.Database 7 | { 8 | public class SequenceFile 9 | { 10 | private FileStream rf; 11 | private BinaryWriter bw; 12 | private BinaryReader br; 13 | private readonly long tableSize = 1024L; //1k 14 | private const int SEQUENCE_ITEM_LENGTH = 8; 15 | private readonly string filePath; 16 | public SequenceFile(String file) 17 | { 18 | filePath = file; 19 | Init(file); 20 | } 21 | 22 | private void Init(string file) 23 | { 24 | try 25 | { 26 | rf = new FileStream(file, FileMode.OpenOrCreate); 27 | bw = new BinaryWriter(rf); 28 | br = new BinaryReader(rf); 29 | if (rf.Length == 0) 30 | { 31 | rf.SetLength(tableSize * SEQUENCE_ITEM_LENGTH); 32 | rf.Position = 0; 33 | bw.Write(0L); 34 | } 35 | } 36 | catch //(Exception ex) 37 | { 38 | bw.Close(); br.Close(); rf.Close(); 39 | throw; 40 | } 41 | 42 | } 43 | 44 | public string FilePath 45 | { 46 | get { return filePath; } 47 | } 48 | 49 | public void Add(long data) 50 | { 51 | rf.Position = 0; 52 | //1.获取长度 53 | long totallen = br.ReadInt64(); 54 | rf.Position = 0; 55 | //2.更新长度 56 | bw.Write(totallen + 1); 57 | rf.Position = (totallen + 1) * SEQUENCE_ITEM_LENGTH; 58 | //3.写入值 59 | bw.Write(data); 60 | } 61 | 62 | public List GetRange(int indexFrom, int length) 63 | { 64 | rf.Position = 0; 65 | //new 一个长度为p0的数组 66 | List values = new List(length); 67 | rf.Position = (indexFrom + 1) * SEQUENCE_ITEM_LENGTH; 68 | for (int i = 0; i < length; i++) 69 | { 70 | long p = br.ReadInt64(); 71 | values.Add(p); 72 | } 73 | return values; 74 | } 75 | 76 | public long GetLength() 77 | { 78 | return Get(-1); 79 | } 80 | 81 | public long Get(int index) 82 | { 83 | rf.Position = (index + 1) * SEQUENCE_ITEM_LENGTH; 84 | return br.ReadInt64(); 85 | } 86 | 87 | //TODO 删除有时似乎还有问题,需要进一步测试 88 | public void Delete(int index) 89 | { 90 | rf.Position = 0; 91 | long totallen = br.ReadInt64(); 92 | if (index > totallen) throw new Exception($"can't delete when totallen={totallen} index={index}"); 93 | rf.Position = 0; 94 | bw.Write(totallen - 1); 95 | //末尾值直接赋值给index的位置,末尾值置0 96 | rf.Position = (totallen - 1 + 1) * SEQUENCE_ITEM_LENGTH; 97 | //用尾部的值替换被删除的值 98 | long lastval = br.ReadInt64(); 99 | bw.Seek(-1 * SEQUENCE_ITEM_LENGTH, SeekOrigin.Current); 100 | bw.Write(0L); 101 | rf.Position = (index + 1) * SEQUENCE_ITEM_LENGTH; 102 | bw.Write(lastval); 103 | bw.Flush();//连续删除有时会出bug,尝试提前flush到文件中 TODO 待验证 104 | } 105 | 106 | public void Clear() 107 | { 108 | rf.SetLength(0); 109 | rf.SetLength(tableSize); 110 | 111 | } 112 | 113 | public void Close() 114 | { 115 | bw.Close(); 116 | br.Close(); 117 | rf.Close(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/NSmartProxy/Extension/CAGen.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Security.Cryptography; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Text; 7 | 8 | namespace NSmartProxy.Extension 9 | { 10 | public class CAGen 11 | { 12 | /// 13 | /// 生成CA,TODO 2 如何通过根证书生成接下来的证书 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static X509Certificate2 GenerateCA(string CertificateName,string hosts = null) 19 | { 20 | SubjectAlternativeNameBuilder sanBuilder = new SubjectAlternativeNameBuilder(); 21 | sanBuilder.AddIpAddress(IPAddress.Loopback); 22 | sanBuilder.AddIpAddress(IPAddress.IPv6Loopback); 23 | sanBuilder.AddDnsName("localhost"); 24 | if (hosts != null) 25 | { 26 | string[] strings = hosts.Split(','); 27 | foreach (var str in strings) 28 | { 29 | sanBuilder.AddDnsName(str); 30 | } 31 | } 32 | 33 | sanBuilder.AddDnsName(Environment.MachineName); 34 | 35 | X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN={CertificateName}"); 36 | 37 | using (RSA rsa = RSA.Create(2048)) 38 | { 39 | var request = new CertificateRequest(distinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); 40 | 41 | request.CertificateExtensions.Add( 42 | new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false)); 43 | 44 | 45 | request.CertificateExtensions.Add( 46 | new X509EnhancedKeyUsageExtension( 47 | new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false)); 48 | 49 | request.CertificateExtensions.Add(sanBuilder.Build()); 50 | 51 | var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650))); 52 | //certificate.FriendlyName = CertificateName; 53 | //return certificate; 54 | 55 | return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "WeNeedASaf3rPassword"), 56 | "WeNeedASaf3rPassword", X509KeyStorageFlags.Exportable); 57 | 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/NSmartProxy/Extension/PeekableBufferBlock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using System.Threading.Tasks.Dataflow; 6 | 7 | namespace NSmartProxy.Infrastructure.Extensions 8 | { 9 | public class PeekableBufferBlock 10 | { 11 | private BufferBlock innerBufferBlock; 12 | private Queue innerQueue; 13 | 14 | public void Post(T item) 15 | { 16 | innerQueue.Enqueue(item); 17 | innerBufferBlock.Post(item); 18 | } 19 | 20 | public async Task ReceiveAsync() 21 | { 22 | 23 | await innerBufferBlock.ReceiveAsync(); 24 | return innerQueue.Dequeue(); 25 | } 26 | 27 | public T Receive() 28 | { 29 | 30 | innerBufferBlock.Receive(); 31 | return innerQueue.Dequeue(); 32 | } 33 | 34 | public PeekableBufferBlock() 35 | { 36 | innerBufferBlock = new BufferBlock(); 37 | innerQueue = new Queue(); 38 | } 39 | 40 | public int Count => innerBufferBlock.Count; 41 | 42 | public T Peek() 43 | { 44 | if (innerQueue.Count == 0) return default(T); 45 | return innerQueue.Peek(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/NSmartProxy/NSPAppGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Net.Sockets; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using NSmartProxy.Data; 9 | 10 | namespace NSmartProxy 11 | { 12 | /// 13 | /// 按host区分的app组,ActivateApp始终是最后一个进来的app。 14 | /// 一个app组中所有的app的协议必须相同。 15 | /// 16 | public class NSPAppGroup : Dictionary 17 | { 18 | public new void Add(string key, NSPApp value) 19 | { 20 | key = key.Replace(" ", ""); 21 | _activateApp = value; 22 | ProtocolInGroup = value.AppProtocol; 23 | base.Add(key, value); 24 | } 25 | 26 | public new NSPApp this[string key] 27 | { 28 | get => base[key.Replace(" ", "")]; 29 | set 30 | { 31 | _activateApp = value; 32 | ProtocolInGroup = value.AppProtocol; base[key.Replace(" ", "")] = value; 33 | } 34 | } 35 | 36 | public NSPApp _activateApp; 37 | 38 | public NSPApp ActivateApp 39 | { 40 | get { return _activateApp; } 41 | // set { _activateApp = value; } 42 | } 43 | public Protocol ProtocolInGroup;//组协议 44 | 45 | public new void Clear() 46 | { 47 | _activateApp = null; 48 | base.Clear(); 49 | } 50 | 51 | public bool IsAllClosed() 52 | { 53 | 54 | foreach (var key in base.Keys) 55 | { 56 | if (!this[key].IsClosed) 57 | { 58 | return false; 59 | } 60 | } 61 | return true; 62 | } 63 | 64 | public TcpListener Listener { get; set; } 65 | public UdpClient UdpClient { get; set; } 66 | public Task UdpTransmissionTask { get; set; } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/NSmartProxy/NSPClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Sockets; 5 | 6 | namespace NSmartProxy 7 | { 8 | public class NSPClient 9 | { 10 | public int ClientID; 11 | public DateTime LastUpdateTime; 12 | public TcpClient ConfigClient; //配置用的socket 13 | 14 | 15 | public Dictionary AppMap; //Appid->app 16 | 17 | public NSPClient() 18 | { 19 | AppMap = new Dictionary(); 20 | } 21 | 22 | /// 23 | /// 注册app并且返回appid(非线程安全) 24 | /// 25 | /// 26 | public int RegisterNewApp() 27 | { 28 | //按顺序分配最大int 29 | int preAppId = 1; 30 | if (AppMap.Count > 0) 31 | preAppId = AppMap.Last().Key + 1; 32 | 33 | NSPApp app = this.AppMap[preAppId] = new NSPApp() 34 | { 35 | AppId = preAppId, 36 | ClientId = ClientID 37 | }; 38 | 39 | return app.AppId; 40 | } 41 | 42 | /// 43 | /// 绑定主机头host到某个端口上,同一端口可以多次绑定 44 | /// 45 | /// 46 | /// 47 | /// 48 | //public int BindHost(string host, int port) 49 | //{ 50 | // if (AppMap[port].HttpApps.Count == 0) 51 | // { 52 | // AppMap. 53 | // } 54 | 55 | // AppMap[port].HttpApps. 56 | //} 57 | 58 | public NSPApp GetApp(int appId) 59 | { 60 | return AppMap[appId]; 61 | } 62 | 63 | //public int Close() 64 | //{ 65 | // //统计关闭的连接数 66 | // int ClosedConnectionCount = 0; 67 | // foreach (var AppKV in AppMap) 68 | // { 69 | // ClosedConnectionCount += AppKV.Value.Close(); 70 | // } 71 | 72 | // return ClosedConnectionCount; 73 | //} 74 | } 75 | } -------------------------------------------------------------------------------- /src/NSmartProxy/NSmartProxy.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Library 5 | net6.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | Always 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/NSmartProxy/ServerModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using NSmartProxy.Infrastructure; 8 | 9 | namespace NSmartProxy 10 | { 11 | public struct ClientIDAppID 12 | { 13 | public int ClientID; 14 | public int AppID; 15 | } 16 | 17 | /// 18 | /// nspclient集合 clientid->NSPClient 19 | /// 20 | public class NSPClientCollection:IEnumerable 21 | { 22 | private ConcurrentDictionary ClientMap; 23 | 24 | public NSPClient this[int index] 25 | { 26 | get => ClientMap[index]; 27 | set => ClientMap[index] = value; 28 | } 29 | public NSPClientCollection() 30 | { 31 | ClientMap = new ConcurrentDictionary(); 32 | } 33 | 34 | public bool ContainsKey(int key) 35 | { 36 | return ClientMap.ContainsKey(key); 37 | } 38 | 39 | public void RegisterNewClient(int key) 40 | { 41 | 42 | ClientMap.TryAdd(key,new NSPClient() 43 | { 44 | ClientID = key, 45 | LastUpdateTime = DateTime.Now 46 | }); 47 | } 48 | 49 | public void UnRegisterClient(int key) 50 | { 51 | //关闭所有连接 52 | //int closedClients = ClientMap[key].Close(); 53 | this.ClientMap.TryRemove(key,out _); 54 | //停止端口侦听 55 | //return closedClients; 56 | } 57 | 58 | public IEnumerator GetEnumerator() 59 | { 60 | return ClientMap.Values.GetEnumerator(); 61 | } 62 | 63 | IEnumerator IEnumerable.GetEnumerator() 64 | { 65 | return GetEnumerator(); 66 | } 67 | } 68 | 69 | 70 | public class AppChangedEventArgs : EventArgs 71 | { 72 | public NSPApp App; 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/NSmartProxy/TcpTunnel.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | 3 | namespace NSmartProxy 4 | { 5 | public class TcpTunnel 6 | { 7 | public TcpClient ConsumerClient; 8 | public TcpClient ClientServerClient; 9 | } 10 | } -------------------------------------------------------------------------------- /src/NSmartProxy/Web/NSmartProxyNew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy/Web/NSmartProxyNew.png -------------------------------------------------------------------------------- /src/NSmartProxy/Web/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/bootstrap-table-expandable.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | $(function () { 3 | $('.table-expandable').each(function () { 4 | var table = $(this); 5 | table.children('thead').children('tr').append(''); 6 | table.children('tbody').children('tr').filter(':odd').hide(); 7 | table.children('tbody').children('tr').filter(':even').click(function () { 8 | var element = $(this); 9 | element.next('tr').toggle('slow'); 10 | element.find(".table-expandable-arrow").toggleClass("up"); 11 | }); 12 | table.children('tbody').children('tr').filter(':even').each(function () { 13 | var element = $(this); 14 | element.append('
'); 15 | }); 16 | }); 17 | }); 18 | })(jQuery); -------------------------------------------------------------------------------- /src/NSmartProxy/Web/bootstrapValidator.css: -------------------------------------------------------------------------------- 1 | /*.bv-form .help-block { 2 | margin-bottom: 0 3 | } 4 | 5 | .bv-form .tooltip-inner { 6 | text-align: left 7 | } 8 | 9 | .nav-tabs li.bv-tab-success > a { 10 | color: #3c763d 11 | } 12 | 13 | .nav-tabs li.bv-tab-error > a { 14 | color: #a94442 15 | }*/ 16 | .has-error { 17 | color: #a94442; 18 | } 19 | 20 | .has-error input { 21 | border-color: #a94442; 22 | } 23 | 24 | .has-success { 25 | color: #67b168; 26 | } 27 | 28 | .has-success input { 29 | border-color: #67b168; 30 | } 31 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/config.html: -------------------------------------------------------------------------------- 1 | 
2 |

证书管理

3 |
4 |
5 | 9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 | 22 |
23 | 24 |
25 | 26 |
27 | 28 | 29 |
30 | 31 | 35 | 42 |
43 | 44 | 45 |
46 |
47 | 48 |
49 |
50 |
51 | 52 |
53 | 54 | 55 |
绑定端口:{Port}
56 |
Pfx证书
57 |

58 | 创建时间:{CreateTime}
59 | 60 | 有效期限:{ToTime}
61 | {Ext} 62 |

63 | 删除证书 64 |
65 |
66 |
67 |
68 | 69 |
70 |

其他配置

71 |
72 |
73 | 77 |
78 |
79 |
80 |
81 | 82 | 83 | 84 |
85 | 86 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/connections.html: -------------------------------------------------------------------------------- 1 | 
2 |

连接

3 |
4 |
5 | 9 |
10 |
11 |
12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 60 | 61 | 62 |
Port(Protocol,Host)User IDAppIdDescriptionStatusConnections
无效内容无效内容无效内容无效内容无效内容无效内容
40 |
连接
41 |
连接
42 |
连接
43 |
无效内容无效内容无效内容无效内容无效内容无效内容
56 |
连接
57 |
连接
58 |
连接
59 |
63 |
-------------------------------------------------------------------------------- /src/NSmartProxy/Web/dashboard.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: .875rem; 3 | } 4 | 5 | .feather { 6 | width: 16px; 7 | height: 16px; 8 | vertical-align: text-bottom; 9 | } 10 | 11 | /* 12 | * Sidebar 13 | */ 14 | 15 | .sidebar { 16 | position: relative; 17 | top: 0; 18 | bottom: 0; 19 | left: 0; 20 | z-index: 100; /* Behind the navbar */ 21 | padding: 48px 0 0; /* Height of navbar */ 22 | box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1); 23 | } 24 | 25 | .sidebar-sticky { 26 | position: relative; 27 | top: 0; 28 | height: calc(100vh - 48px); 29 | padding-top: .5rem; 30 | overflow-x: hidden; 31 | overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ 32 | } 33 | 34 | @supports ((position: -webkit-sticky) or (position: sticky)) { 35 | .sidebar-sticky { 36 | position: -webkit-sticky; 37 | position: sticky; 38 | } 39 | } 40 | 41 | .sidebar .nav-link { 42 | font-weight: 500; 43 | color: #333; 44 | } 45 | 46 | .sidebar .nav-link .feather { 47 | margin-right: 4px; 48 | color: #999; 49 | } 50 | 51 | .sidebar .nav-link.active { 52 | color: #007bff; 53 | } 54 | 55 | .sidebar .nav-link:hover .feather, 56 | .sidebar .nav-link.active .feather { 57 | color: inherit; 58 | } 59 | 60 | .sidebar-heading { 61 | font-size: .75rem; 62 | text-transform: uppercase; 63 | } 64 | 65 | /* 66 | * Content 67 | */ 68 | 69 | [role="main"] { 70 | padding-top: 8px; /* Space for fixed navbar */ 71 | } 72 | 73 | 74 | 75 | @media (min-width: 768px) { 76 | [role="main"] { 77 | padding-top: 48px; /* Space for fixed navbar */ 78 | } 79 | } 80 | 81 | /* 82 | * Navbar 83 | */ 84 | 85 | .navbar-brand { 86 | padding-top: .75rem; 87 | padding-bottom: .75rem; 88 | font-size: 1rem; 89 | background-color: rgba(0, 0, 0, .25); 90 | box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25); 91 | } 92 | 93 | .navbar .form-control { 94 | padding: .75rem 1rem; 95 | border-width: 0; 96 | border-radius: 0; 97 | } 98 | 99 | .form-control-dark { 100 | color: #fff; 101 | background-color: rgba(255, 255, 255, .1); 102 | border-color: rgba(255, 255, 255, .1); 103 | } 104 | 105 | .form-control-dark:focus { 106 | border-color: transparent; 107 | box-shadow: 0 0 0 3px rgba(255, 255, 255, .25); 108 | } 109 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/dashboard.html: -------------------------------------------------------------------------------- 1 | 
2 |

仪表盘

3 |
4 |
5 | 7 |
8 |
9 |
10 | 11 |
12 |
13 | 14 | 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 |

最新日志

26 | 27 |
28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
LineContent
1,001无效内容
1,002无效内容
1,003无效内容
1,003无效内容
1,004无效内容
1,005无效内容
1,006无效内容
78 |
79 |
80 | 82 |
83 |
84 |
-------------------------------------------------------------------------------- /src/NSmartProxy/Web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy/Web/favicon.ico -------------------------------------------------------------------------------- /src/NSmartProxy/Web/loading-s.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxy/Web/loading-s.gif -------------------------------------------------------------------------------- /src/NSmartProxy/Web/login.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | NSmartProxy · Login 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 33 | 34 | 35 | 36 | 37 | 53 | 54 | 55 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/logs.html: -------------------------------------------------------------------------------- 1 | 
2 |

日志

3 |
4 |
5 | 7 |
8 | 9 |
10 |
11 | 12 |
13 | 14 | 15 |
16 |
17 |
18 | 19 | 20 | 21 | 22 |
-------------------------------------------------------------------------------- /src/NSmartProxy/Web/logs.js: -------------------------------------------------------------------------------- 1 | //@ sourceURL= log.js 2 | 3 | (function () { 4 | refreshLog(); 5 | }()); 6 | 7 | function getLogFiles() { 8 | $.get(basepath 9 | + "GetLogFiles", 10 | function (res) { 11 | var data = res.Data; 12 | var html = "
"; 13 | for (i in data) { 14 | html += " "; 18 | i++; 19 | } 20 | $("#divOldLog").html(html); 21 | } 22 | ); 23 | }; 24 | 25 | function getLogFile(filekey) { 26 | var apiUrl = basepath + "GetLogFile?filekey=" + filekey; 27 | window.open(apiUrl); 28 | } 29 | 30 | function getLogFileInfo(lines) { 31 | var apiUrl = basepath + "GetLogFileInfo?lastLines=" + lines; 32 | $.get(apiUrl, 33 | function (res) { 34 | var data = res.Data; 35 | var logText = ""; 36 | for (i in data) { 37 | logText += data[i] + "\r\n"; 38 | } 39 | $("#tbxLog").val(logText); 40 | } 41 | ); 42 | } 43 | 44 | function refreshLog() { 45 | getLogFiles(); 46 | getLogFileInfo(20); 47 | setTimeout(scrollToBottom, 200); 48 | } 49 | 50 | function scrollToBottom() { 51 | $('#tbxLog').scrollTop($('#tbxLog')[0].scrollHeight); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/main.js: -------------------------------------------------------------------------------- 1 | //TODO 调试用 2 | var basepath = "/";//api根地址,这里需要和配置文件一致 3 | //var basepath = "http://localhost:12309/"; //调试时请把地址改成这个 4 | 5 | //hashchange事件,路由是如此实现的 6 | (function () { 7 | if ("onhashchange" in window) { // event supported? 8 | window.onhashchange = function () { 9 | hashChanged(window.location.hash); 10 | }; 11 | } else { // event not supported: 12 | var storedHash = window.location.hash; 13 | window.setInterval(function () { 14 | if (window.location.hash !== storedHash) { 15 | storedHash = window.location.hash; 16 | hashChanged(storedHash); 17 | } 18 | }, 19 | 100); 20 | } 21 | 22 | function hashChanged(storedHash) { 23 | storedHash = loadContent(storedHash); 24 | if (location.pathname.toUpperCase() !== "/LOGIN.HTML") { 25 | if (getCookie("NSPTK").length < 1) { 26 | location.href = "/login.html"; 27 | } 28 | } 29 | } 30 | 31 | function loadContent(storedHash) { 32 | if (this.location.href.indexOf("login.html") < 0 && this.location.href.indexOf('#') < 0) { 33 | this.location.href += "#dashboard"; 34 | return; 35 | } 36 | storedHash = "#" + storedHash; 37 | var compName = storedHash.substring(storedHash.lastIndexOf("#") + 1); 38 | //发布时注释掉 39 | $.get(compName + ".html?" + new Date(), function (src) { 40 | $("#content").html(src); 41 | $.getScript(compName + ".js");//加载模板 42 | //加载图标 43 | if (feather) 44 | feather.replace(); 45 | }); 46 | $(".active").removeClass("active"); 47 | var hrefTag = "#" + storedHash.substring(storedHash.lastIndexOf("#") + 1); 48 | $("a[href='" + hrefTag + "']").addClass("active"); 49 | return storedHash; 50 | } 51 | 52 | $(document).ready(function () { 53 | loadContent(window.location.hash); 54 | //选中项 55 | } 56 | ); 57 | } 58 | 59 | )(); 60 | 61 | function redAlert(msg) { 62 | $("#red_alert span:first").html(msg); 63 | $("#red_alert").show(); 64 | } 65 | function greenAlert(msg) { 66 | $("#green_alert span:first").html(msg); 67 | $("#green_alert").show(); 68 | } 69 | 70 | ///处理nsp发回的统一数据,如果有错则弹框,否则返回真 71 | function processNSPResult(res) { 72 | return true; 73 | } 74 | 75 | function getCookie(cookieName) { 76 | var strCookie = document.cookie; 77 | var arrCookie = strCookie.split("; "); 78 | for (var i = 0; i < arrCookie.length; i++) { 79 | var arr = arrCookie[i].split("="); 80 | if (cookieName === arr[0]) { 81 | return arr[1]; 82 | } 83 | } 84 | return ""; 85 | } 86 | 87 | function delCookie(name) { 88 | var exp = new Date(); 89 | exp.setTime(exp.getTime() - 1); 90 | var cval = getCookie(name); 91 | if (cval !== null) document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); 92 | } 93 | 94 | function signOut() { 95 | delCookie("NSPTK"); 96 | location.href = "/login.html"; 97 | } 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/NSmartProxy/Web/signin.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | display: -ms-flexbox; 8 | display: flex; 9 | -ms-flex-align: center; 10 | align-items: center; 11 | padding-top: 40px; 12 | padding-bottom: 40px; 13 | background-color: #f5f5f5; 14 | } 15 | 16 | .form-signin { 17 | width: 100%; 18 | max-width: 330px; 19 | padding: 15px; 20 | margin: auto; 21 | } 22 | 23 | .form-signin .checkbox { 24 | font-weight: 400; 25 | } 26 | 27 | .form-signin .form-control { 28 | position: relative; 29 | box-sizing: border-box; 30 | height: auto; 31 | padding: 10px; 32 | font-size: 16px; 33 | } 34 | 35 | .form-signin .form-control:focus { 36 | z-index: 2; 37 | } 38 | 39 | .form-signin input[type="email"] { 40 | margin-bottom: -1px; 41 | border-bottom-right-radius: 0; 42 | border-bottom-left-radius: 0; 43 | } 44 | 45 | .form-signin input[type="password"] { 46 | margin-bottom: 10px; 47 | border-top-left-radius: 0; 48 | border-top-right-radius: 0; 49 | } 50 | -------------------------------------------------------------------------------- /src/NSmartProxyClient/Dockerfile: -------------------------------------------------------------------------------- 1 |  2 | #need combile 1st. 3 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS runtime 4 | WORKDIR /app 5 | COPY / /app/ 6 | ENTRYPOINT ["dotnet", "NSmartProxyClient.dll"] -------------------------------------------------------------------------------- /src/NSmartProxyClient/NSmartProxyClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | true 7 | 8 | 9 | 10 | ../../test/build/nspclient 11 | 12 | 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Always 35 | Always 36 | true 37 | 38 | 39 | 40 | 41 | 42 | 43 | PreserveNewest 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/NSmartProxyClient/Program.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy.Shared; 2 | using PeterKottas.DotNetCore.WindowsService; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace NSmartProxy.ServerHost 9 | { 10 | public class Program 11 | { 12 | static void Main() 13 | { 14 | //wait 15 | ServiceRunner.Run(config => 16 | { 17 | var name = Global.NSPClientServiceDisplayName; 18 | config.SetDisplayName(Global.NSPClientServiceName); 19 | config.SetName(Global.NSPClientServiceDisplayName); 20 | config.SetDescription(NSPVersion.NSmartProxyClientName); 21 | 22 | config.Service(serviceConfig => 23 | { 24 | serviceConfig.ServiceFactory((extraArguments, controller) => 25 | { 26 | return new NSmartProxyClient(); 27 | }); 28 | 29 | serviceConfig.OnStart((service, extraParams) => 30 | { 31 | Console.WriteLine("Service {0} started", name); 32 | Task.Run(() => service.Start(extraParams.ToArray())); 33 | }); 34 | 35 | serviceConfig.OnStop(service => 36 | { 37 | Console.WriteLine("Service {0} stopped", name); 38 | Task.Run(() => service.Stop()); 39 | }); 40 | 41 | serviceConfig.OnError(e => 42 | { 43 | Console.WriteLine("Service {0} errored with exception : {1}", name, e.Message); 44 | }); 45 | }); 46 | 47 | 48 | }); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/NSmartProxyClient/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "NSmartProxyClient": { 4 | "commandName": "Project", 5 | "commandLineArgs": "-p admin -pwd admin" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/NSmartProxyClient/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProviderWebPort": 12309, 3 | "ProviderAddress": "127.0.0.1", 4 | 5 | //反向代理客户端,可以配置多个 6 | "Clients": [ 7 | 8 | //{ 9 | // "IP": "127.0.0.1", 10 | // "TargetServicePort": "82", 11 | // "Host": "haha.tmoonlight.top", 12 | // "Protocol": "HTTP", 13 | // "ConsumerPort": "443", 14 | // "Description": "测试备注" 15 | //}, 16 | 17 | { 18 | "IP": "127.0.0.1", 19 | "TargetServicePort": "5901", 20 | "protocol": "UDP", 21 | "ConsumerPort": "22222" 22 | }, 23 | { 24 | "IP": "127.0.0.1", 25 | "TargetServicePort": "8000", 26 | "ConsumerPort": "52999", 27 | "protocol": "TCP", 28 | "IsCompress": true 29 | }, 30 | 31 | { 32 | "IP": "127.0.0.1", 33 | "TargetServicePort": "2996", 34 | "ConsumerPort": "62997", 35 | "protocol": "TCP", 36 | "IsCompress": true 37 | }, 38 | { 39 | "IP": "127.0.0.1", 40 | "TargetServicePort": "80", 41 | //"Host": "o2.kd.com", 42 | "ConsumerPort": "80" 43 | }, 44 | { 45 | "IP": "127.0.0.1", 46 | "TargetServicePort": "3389", 47 | "ConsumerPort": "12345" 48 | } 49 | //{ 50 | // "IP": "127.0.0.1", 51 | // "TargetServicePort": "3389" 52 | //} 53 | ] 54 | } -------------------------------------------------------------------------------- /src/NSmartProxyClient/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/NSmartProxyWinService/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/NSmartProxyWinService/NSPClientService.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxyWinService 2 | { 3 | partial class NSPClientService 4 | { 5 | /// 6 | /// 必需的设计器变量。 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// 清理所有正在使用的资源。 12 | /// 13 | /// 如果应释放托管资源,为 true;否则为 false。 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region 组件设计器生成的代码 24 | 25 | /// 26 | /// 设计器支持所需的方法 - 不要修改 27 | /// 使用代码编辑器修改此方法的内容。 28 | /// 29 | private void InitializeComponent() 30 | { 31 | // 32 | // NSPClientService 33 | // 34 | this.ServiceName = "NSPClientService"; 35 | 36 | } 37 | 38 | #endregion 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/NSmartProxyWinService/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.ServiceProcess; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace NSmartProxyWinService 9 | { 10 | static class Program 11 | { 12 | /// 13 | /// 应用程序的主入口点。 14 | /// 15 | static void Main(string[] args) 16 | { 17 | if (Environment.UserInteractive) 18 | { 19 | NSPClientService testService = new NSPClientService(); 20 | testService.TestStartupAndStop(args); 21 | } 22 | else 23 | { 24 | ServiceBase[] ServicesToRun; 25 | ServicesToRun = new ServiceBase[] 26 | { 27 | new NSPClientService() 28 | }; 29 | ServiceBase.Run(ServicesToRun); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NSmartProxyWinService/ProjectInstaller.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace NSmartProxyWinService 2 | { 3 | partial class ProjectInstaller 4 | { 5 | /// 6 | /// 必需的设计器变量。 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// 清理所有正在使用的资源。 12 | /// 13 | /// 如果应释放托管资源,为 true;否则为 false。 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region 组件设计器生成的代码 24 | 25 | /// 26 | /// 设计器支持所需的方法 - 不要修改 27 | /// 使用代码编辑器修改此方法的内容。 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller(); 32 | this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller(); 33 | // 34 | // serviceProcessInstaller1 35 | // 36 | this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; 37 | this.serviceProcessInstaller1.Password = null; 38 | this.serviceProcessInstaller1.Username = null; 39 | // 40 | // serviceInstaller1 41 | // 42 | this.serviceInstaller1.Description = "NSmartProxy客户端服务"; 43 | this.serviceInstaller1.DisplayName = "NSPClient"; 44 | this.serviceInstaller1.ServiceName = "NSPClient"; 45 | this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic; 46 | // 47 | // ProjectInstaller 48 | // 49 | this.Installers.AddRange(new System.Configuration.Install.Installer[] { 50 | this.serviceProcessInstaller1, 51 | this.serviceInstaller1}); 52 | 53 | } 54 | 55 | #endregion 56 | 57 | private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1; 58 | private System.ServiceProcess.ServiceInstaller serviceInstaller1; 59 | } 60 | } -------------------------------------------------------------------------------- /src/NSmartProxyWinService/ProjectInstaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Configuration.Install; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using NSmartProxy.Shared; 9 | 10 | namespace NSmartProxyWinService 11 | { 12 | [RunInstaller(true)] 13 | public partial class ProjectInstaller : System.Configuration.Install.Installer 14 | { 15 | public ProjectInstaller() 16 | { 17 | InitializeComponent(); 18 | this.serviceInstaller1.DisplayName = Global.NSPClientServiceDisplayName; 19 | this.serviceInstaller1.ServiceName = Global.NSPClientServiceName; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NSmartProxyWinService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("NSmartProxyWinService")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NSmartProxyWinService")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", Watch = true)] 17 | 18 | // 将 ComVisible 设置为 false 会使此程序集中的类型 19 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 20 | //请将此类型的 ComVisible 特性设置为 true。 21 | [assembly: ComVisible(false)] 22 | 23 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 24 | [assembly: Guid("d5488369-60d1-47e5-880d-8d5f49a0d777")] 25 | 26 | // 程序集的版本信息由下列四个值组成: 27 | // 28 | // 主版本 29 | // 次版本 30 | // 生成号 31 | // 修订号 32 | // 33 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 34 | // 方法是按如下所示使用“*”: : 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("1.0.0.0")] 37 | [assembly: AssemblyFileVersion("1.0.0.0")] 38 | -------------------------------------------------------------------------------- /src/NSmartProxyWinService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/NSmartProxyWinform/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 10 | 11 | 12 | 13 | 14 | A comma-separated list of error codes that can be safely ignored in assembly verification. 15 | 16 | 17 | 18 | 19 | 'false' to turn off automatic generation of the XML Schema file. 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Log4netLogger.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy.Interfaces; 2 | using System; 3 | 4 | namespace NSmartProxyWinform 5 | { 6 | public class Log4netLogger : INSmartLogger 7 | { 8 | public delegate void BeforeWriteLogDelegate(object message); 9 | public BeforeWriteLogDelegate BeforeWriteLog; 10 | public void Debug(object message) 11 | { 12 | BeforeWriteLog(message); 13 | Program.Logger.Debug(message); 14 | } 15 | 16 | public void Error(object message, Exception ex) 17 | { 18 | BeforeWriteLog(message); 19 | Program.Logger.Error(message, ex); 20 | } 21 | 22 | public void Info(object message) 23 | { 24 | BeforeWriteLog(message); 25 | Program.Logger.Info(message); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Program.cs: -------------------------------------------------------------------------------- 1 | using log4net; 2 | using log4net.Config; 3 | using Microsoft.Extensions.Configuration; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace NSmartProxyWinform 13 | { 14 | 15 | static class Program 16 | { 17 | private static Mutex mutex = new Mutex(true, "{41ACBA9E-9699-4766-891B-57F325420A78}"); 18 | 19 | public static IConfigurationRoot Configuration { get; set; } 20 | public static ILog Logger; 21 | 22 | public static string LoggerPath = "log4net.config"; 23 | public static string LoggerConfigPath = "log4net.config"; 24 | public const string LOGGER_REPO_NAME = "NSmartClientRouterRepository"; 25 | public const string CONFIG_FILE_PATH = "./appsettings.json"; 26 | 27 | //public static string[] Args; 28 | /// 29 | /// 应用程序的主入口点。 30 | /// 31 | [STAThread] 32 | static void Main(string[] args) 33 | { 34 | if (!mutex.WaitOne(3, false)) 35 | { 36 | string msg = "Another instance of the program is running."; 37 | //Logger.Error(msg, new Exception(msg)); 38 | MessageBox.Show(msg); 39 | return; 40 | } 41 | 42 | var loggerRepository = LogManager.CreateRepository(LOGGER_REPO_NAME); 43 | var config = XmlConfigurator.Configure(loggerRepository, new FileInfo(LoggerConfigPath)); 44 | //BasicConfigurator.Configure(loggerRepository); 45 | Program.Logger = LogManager.GetLogger(loggerRepository.Name, "NSmartServerClient"); 46 | if (!loggerRepository.Configured) throw new Exception("log config failed."); 47 | var builder = new ConfigurationBuilder() 48 | .SetBasePath(Directory.GetCurrentDirectory()) 49 | .AddJsonFile(CONFIG_FILE_PATH); 50 | Configuration = builder.Build(); 51 | 52 | Application.EnableVisualStyles(); 53 | Application.SetCompatibleTextRenderingDefault(false); 54 | var clientForm = new ClientMngr(); 55 | //Application.ApplicationExit += (sender, e) => 56 | //{ 57 | // clientForm.Close(); 58 | //}; 59 | 60 | Application.Run(clientForm); 61 | } 62 | 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("NSmartProxyWinform")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NSmartProxyWinform")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", Watch = true)] 17 | 18 | // 将 ComVisible 设置为 false 会使此程序集中的类型 19 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 20 | //请将此类型的 ComVisible 特性设置为 true。 21 | [assembly: ComVisible(false)] 22 | 23 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 24 | [assembly: Guid("b55f3df3-6657-4204-aeeb-b2360fc5fab1")] 25 | 26 | // 程序集的版本信息由下列四个值组成: 27 | // 28 | // 主版本 29 | // 次版本 30 | // 生成号 31 | // 修订号 32 | // 33 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 34 | // 方法是按如下所示使用“*”: : 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("1.0.0.0")] 37 | [assembly: AssemblyFileVersion("1.0.0.0")] 38 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace NSmartProxyWinform.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("1")] 29 | public string test { 30 | get { 31 | return ((string)(this["test"])); 32 | } 33 | set { 34 | this["test"] = value; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 1 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/NSmartProxyNew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/NSmartProxyNew.png -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/Permission_12796.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/Permission_12796.png -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/UserProfilenode_8706.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/UserProfilenode_8706.png -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/base_checkmark_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/base_checkmark_32.png -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/servicepaused.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/servicepaused.ico -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/servicerunning.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/servicerunning.ico -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Resources/servicestopped.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/Resources/servicestopped.ico -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Util/HotKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | 7 | namespace NSmartProxyWinform.Util 8 | { 9 | public class HotKey 10 | { 11 | //如果函数执行成功,返回值不为0。 12 | //如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。 13 | [DllImport("user32.dll", SetLastError = true)] 14 | public static extern bool RegisterHotKey( 15 | IntPtr hWnd, //要定义热键的窗口的句柄 16 | int id, //定义热键ID(不能与其它ID重复) 17 | KeyModifiers fsModifiers, //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效 18 | Keys vk //定义热键的内容 19 | ); 20 | 21 | [DllImport("user32.dll", SetLastError = true)] 22 | public static extern bool UnregisterHotKey( 23 | IntPtr hWnd, //要取消热键的窗口的句柄 24 | int id //要取消热键的ID 25 | ); 26 | 27 | //定义了辅助键的名称(将数字转变为字符以便于记忆,也可去除此枚举而直接使用数值) 28 | [Flags()] 29 | public enum KeyModifiers 30 | { 31 | None = 0, 32 | Alt = 1, 33 | Ctrl = 2, 34 | Shift = 4, 35 | WindowsKey = 8 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Util/TextBoxEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace NSmartProxyWinform.Util 10 | { 11 | public class TextBoxEx : TextBox 12 | { 13 | public String PlaceHolderStr { get; set; } 14 | protected override void WndProc(ref Message m) 15 | { 16 | base.WndProc(ref m); 17 | if (m.Msg == 0xF || m.Msg == 0x133) 18 | { 19 | WmPaint(ref m); 20 | } 21 | } 22 | private void WmPaint(ref Message m) 23 | { 24 | Graphics g = Graphics.FromHwnd(base.Handle); 25 | if (!String.IsNullOrEmpty(this.PlaceHolderStr) && string.IsNullOrEmpty(this.Text)) 26 | g.DrawString(this.PlaceHolderStr, this.Font, new SolidBrush(Color.Gray), 0, 0); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/Util/WinServiceHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Configuration.Install; 5 | using System.Linq; 6 | using System.ServiceProcess; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace NSmartProxyWinform.Util 11 | { 12 | public static class WinServiceHelper 13 | { 14 | /// 15 | /// 判断服务是否存在 16 | /// 17 | /// 18 | /// 19 | public static bool IsServiceExisted(string serviceName) 20 | { 21 | ServiceController[] services = ServiceController.GetServices(); 22 | foreach (ServiceController sc in services) 23 | { 24 | if (sc.ServiceName.ToLower() == serviceName.ToLower()) 25 | { 26 | return true; 27 | } 28 | } 29 | return false; 30 | } 31 | 32 | /// 33 | /// 安装服务 34 | /// 35 | /// 36 | public static void InstallService(string serviceFilePath) 37 | { 38 | using (AssemblyInstaller installer = new AssemblyInstaller()) 39 | { 40 | installer.UseNewContext = true; 41 | installer.Path = serviceFilePath; 42 | 43 | IDictionary savedState = new Hashtable(); 44 | installer.Install(savedState); 45 | installer.Commit(savedState); 46 | } 47 | } 48 | 49 | /// 50 | /// 卸载服务 51 | /// 52 | /// 53 | public static void UninstallService(string serviceFilePath) 54 | { 55 | using (AssemblyInstaller installer = new AssemblyInstaller()) 56 | { 57 | installer.UseNewContext = true; 58 | installer.Path = serviceFilePath; 59 | installer.Uninstall(null); 60 | } 61 | } 62 | /// 63 | /// 启动服务 64 | /// 65 | /// 66 | public static void ServiceStart(string serviceName) 67 | { 68 | using (ServiceController control = new ServiceController(serviceName)) 69 | { 70 | if (control.Status == ServiceControllerStatus.Stopped) 71 | { 72 | control.Start(); 73 | } 74 | } 75 | } 76 | 77 | /// 78 | /// 停止服务 79 | /// 80 | /// 81 | public static void ServiceStop(string serviceName) 82 | { 83 | using (ServiceController control = new ServiceController(serviceName)) 84 | { 85 | if (control.Status == ServiceControllerStatus.Running) 86 | { 87 | control.Stop(); 88 | } 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProviderWebPort": 12309, //Configure the port of the NSPServer service 3 | "ProviderAddress": "127.0.0.1", //Configure the address of the NSPServer service 4 | 5 | //NSPClients, you can configure multiple 6 | "Clients": [ 7 | { 8 | "IP": "127.0.0.1", //Reverse proxy machine ip 9 | "TargetServicePort": "3389", //Port of the reverse proxy service 10 | "ConsumerPort": "13389" //External network access port, if occupied,the nspclient will allocate ports in order from 20000 11 | }, 12 | { 13 | "IP": "127.0.0.1", 14 | "TargetServicePort": "80" 15 | }, 16 | { 17 | "IP": "127.0.0.1", 18 | "TargetServicePort": "21" 19 | } 20 | ] 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/i18n/en.txt: -------------------------------------------------------------------------------- 1 | Start 2 | Open in Explorer 3 | Start 4 | Configuration... 5 | Exit 6 | Log 7 | Application 8 | Save configuration 9 | Restore configuration 10 | Add 11 | Copy 12 | Delete 13 | Node configuration 14 | * : If the external network port is 0 or empty, the port will automatically assigned by the server. 15 | Intranet addr. 16 | Intranet port 17 | External port (*optional) 18 | External addr. 19 | Test 20 | Server address 21 | Port 22 | Service 23 | Uninstall windows service 24 | Register windows service 25 | Anonymous 26 | 27 | Configuration 28 | Login 29 | Anonymous Login 30 | Password 31 | Username 32 | 保存成功 33 | 保存成功 34 | 登录成功 35 | 登录失败 36 | 登录成功 37 | 已登录 38 | 保存成功 39 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/i18n/ol.txt: -------------------------------------------------------------------------------- 1 | 开始 2 | 资源管理器中打开 3 | 启动内网穿透 4 | 配置... 5 | 退出程序 6 | 日志 7 | 应用 8 | 保存配置 9 | 还原配置 10 | 添加 11 | 复制 12 | 删除 13 | 节点配置 14 | * : 外网端口为0或者空则代表端口由服务端自动分派。 15 | 内网地址 16 | 内网端口 17 | 外网端口(*可选) 18 | 外网服务器 19 | 测试 20 | 服务器地址 21 | 端口 22 | 服务 23 | 卸载windows服务 24 | 注册为windows服务 25 | 未登录 26 | <随机> 27 | 配置对话框 28 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/i18n/zh.txt: -------------------------------------------------------------------------------- 1 | 开始 2 | 资源管理器中打开 3 | 启动内网穿透 4 | 配置... 5 | 退出程序 6 | 日志 7 | 应用 8 | 保存配置 9 | 还原配置 10 | 添加 11 | 复制 12 | 删除 13 | 节点配置 14 | * : 外网端口为0或者空则代表端口由服务端自动分派。 15 | 内网地址 16 | 内网端口 17 | 外网端口(*可选) 18 | 外网服务器 19 | 测试 20 | 服务器地址 21 | 端口 22 | 服务 23 | 卸载windows服务 24 | 注册为windows服务 25 | 未登录 26 | <随机> 27 | 配置对话框 28 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/NSmartProxyWinform/nsp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/src/NSmartProxyWinform/nsp.ico -------------------------------------------------------------------------------- /src/TestBed/NSmartProxy.ConsoleTest/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NSmartProxy.ConsoleTest 6 | { 7 | class Class1 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/TestBed/NSmartProxy.ConsoleTest/NSmartProxy.ConsoleTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | TRACE;DEBUG;DEBUG_MESSAGES 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/TestBed/NSmartProxy.ConsoleTest/Program.cs: -------------------------------------------------------------------------------- 1 | using LiteNetLib; 2 | using LiteNetLib.Utils; 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace NSmartProxy.ConsoleTest 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | //var p = new Program(); 14 | //p.Server(); 15 | (new HolePunchServerTest()).Run(); 16 | 17 | } 18 | 19 | Random rand = new Random(996); 20 | public void Server() 21 | { 22 | EventBasedNetListener listener = new EventBasedNetListener(); 23 | NetManager server = new NetManager(listener); 24 | server.Start(9050 /* port */); 25 | 26 | listener.ConnectionRequestEvent += request => 27 | { 28 | if (server.PeersCount < 10 /* max connections */) 29 | request.AcceptIfKey("SomeConnectionKey"); 30 | else 31 | request.Reject(); 32 | }; 33 | 34 | listener.PeerConnectedEvent += peer => 35 | { 36 | Console.WriteLine("We got connection: {0}", peer.EndPoint); // Show peer ip 37 | NetDataWriter writer = new NetDataWriter(); // Create writer class 38 | writer.Put("Hello client!"); // Put some string 39 | peer.Send(writer, DeliveryMethod.ReliableOrdered); // Send with reliability 40 | }; 41 | 42 | //轮询才能触发事件 43 | while (!Console.KeyAvailable) 44 | { 45 | server.PollEvents(); 46 | Thread.Sleep(15); 47 | } 48 | 49 | server.Stop(); 50 | } 51 | 52 | public void Client() 53 | { 54 | EventBasedNetListener listener = new EventBasedNetListener(); 55 | NetManager client = new NetManager(listener); 56 | client.Start(); 57 | client.Connect("localhost" /* host ip or name */, 9050 /* port */, "SomeConnectionKey" /* text key or NetDataWriter */); 58 | listener.NetworkReceiveEvent += (fromPeer, dataReader, deliveryMethod) => 59 | { 60 | Console.WriteLine("We got: {0}", dataReader.GetString(100 /* max length of string */)); 61 | dataReader.Recycle(); 62 | }; 63 | 64 | //轮询才能触发事件 65 | while (!Console.KeyAvailable) 66 | { 67 | client.PollEvents(); 68 | Thread.Sleep(15); 69 | } 70 | 71 | client.Stop(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/TestBed/NSmartProxy.P2PClient - 副本/NSmartProxy.P2PClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | TRACE;DEBUG_MESSAGES 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/TestBed/NSmartProxy.P2PClient/NSmartProxy.P2PClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | TRACE;DEBUG_MESSAGES 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/build_simple.cmd: -------------------------------------------------------------------------------- 1 | rem windows only 2 | rem NSP v1.1 3 | @ECHO off 4 | 5 | set Ver=v1.2_final4 6 | set BuildPath=%~dp0../build 7 | 8 | set nsp_server_path=%BuildPath%/nspclient_%Ver% 9 | set nsp_client_path=%BuildPath%/nspserver_%Ver% 10 | set nsp_client_winfform_path=%BuildPath%/nspclient_winform_%Ver% 11 | 12 | rem del %~dp0/../build/*.* 13 | rem NSPClient 14 | dotnet publish .\NSmartProxyClient\NSmartProxyClient.csproj -c release -o %nsp_server_path% 15 | 16 | rem NSPServer 17 | dotnet publish .\NSmartProxy.ServerHost\NSmartProxy.ServerHost.csproj -c release -o %nsp_client_path% 18 | 19 | rem NSPWinform 20 | MSBuild .\NSmartProxyWinform\NSmartProxyWinform.csproj /t:build /p:OutDir=%nsp_client_winfform_path% 21 | powershell del %nsp_client_winfform_path%/*.pdb 22 | powershell del %nsp_client_winfform_path%/*.xml 23 | 24 | rem ilmerge 25 | rem ruined :< 26 | 27 | rem compress 28 | powershell Compress-Archive -Path '%nsp_server_path%/*' -DestinationPath '%BuildPath%/nspclient_%Ver%.zip' -Force 29 | powershell Compress-Archive -Path '%nsp_client_path%/*' -DestinationPath '%BuildPath%/nspserver_%Ver%.zip' -Force 30 | powershell Compress-Archive -Path '%nsp_client_winfform_path%/*' -DestinationPath '%BuildPath%/nspclient_winform_%Ver%.zip' -Force 31 | 32 | powershell explorer %~dp0..\build 33 | pause -------------------------------------------------------------------------------- /src/build_test.cmd: -------------------------------------------------------------------------------- 1 | rem windows only 2 | rem NSP v1.2 3 | @ECHO off 4 | 5 | set Ver=v1.2pre3 6 | set BuildPath=%~dp0../build 7 | 8 | set nsp_client_path=%BuildPath%/nspclient_%Ver% 9 | set nsp_server_path=%BuildPath%/nspserver_%Ver% 10 | 11 | 12 | set nsp_client_scd_win_path=%BuildPath%/nspclient_scd_win_%Ver% 13 | 14 | 15 | 16 | set nsp_server_scd_win_path=%BuildPath%/nspserver_scd_win_%Ver% 17 | 18 | 19 | set nsp_client_winfform_path=%BuildPath%/nspclient_winform_%Ver% 20 | 21 | rem del %~dp0/../build/*.* 22 | rem NSPClient 23 | dotnet publish .\NSmartProxyClient\NSmartProxyClient.csproj -c release -o %nsp_client_path% 24 | 25 | rem NSPServer 26 | dotnet publish .\NSmartProxy.ServerHost\NSmartProxy.ServerHost.csproj -c release -o %nsp_server_path% 27 | 28 | rem NSPClient_SCD 29 | dotnet publish .\NSmartProxyClient\NSmartProxyClient.csproj -r win-x64 -c Release /p:PublishSingleFile=true -o %nsp_client_scd_win_path% 30 | 31 | 32 | rem NSPServer_SCD 33 | dotnet publish .\NSmartProxy.ServerHost\NSmartProxy.ServerHost.csproj -r win-x64 -c Release /p:PublishSingleFile=true -o %nsp_server_scd_win_path% 34 | 35 | rem NSPWinform 36 | MSBuild .\NSmartProxyWinform\NSmartProxyWinform.csproj /t:build /p:OutDir=%nsp_client_winfform_path% 37 | powershell del %nsp_client_winfform_path%/*.pdb 38 | powershell del %nsp_client_winfform_path%/*.xml 39 | 40 | rem ilmerge 41 | rem ruined :< 42 | 43 | rem compress 44 | 45 | powershell explorer %~dp0..\build 46 | pause -------------------------------------------------------------------------------- /src/deploy.cmd: -------------------------------------------------------------------------------- 1 | rem *** 个人用的部署到树莓派的脚本 *** 2 | xcopy %~dp0..\build\nspserver_v1.2 z:\nsmart /y /e /i 3 | curl "http://2017studio.imwork.net:7002/index.html?processname=nspserver&action=restart" 4 | pause -------------------------------------------------------------------------------- /src/global.temp: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "2.2.104" 4 | } 5 | } -------------------------------------------------------------------------------- /test/TcpClient/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Net.Sockets; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace TCPTester.Client 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | Console.WriteLine("*** Tcp Client ***"); 17 | TcpClient tcpClient = new TcpClient(); 18 | tcpClient.Connect("127.0.0.1", 64321); 19 | //tcpClient.Connect("192.168.1.2", 12306); 20 | var stream = tcpClient.GetStream(); 21 | 22 | Task.Run(() => 23 | { 24 | 25 | byte[] buffer = new byte[4096]; 26 | while (true) 27 | { 28 | try 29 | { 30 | int readResultLength = stream.Read(buffer, 0, buffer.Length); 31 | 32 | if (readResultLength == 0) break; 33 | Console.WriteLine(ASCIIEncoding.ASCII.GetString(buffer, 0, readResultLength).Trim()); 34 | } 35 | catch 36 | { 37 | Console.WriteLine("stream closed ungracefully"); 38 | break; 39 | } 40 | } 41 | }); 42 | int x = 0; 43 | int count = 0; 44 | //数据传输测试 45 | while (count < 6) 46 | { 47 | string str = "test" + count;//Console.ReadLine(); 48 | if (str == "test5") 49 | { 50 | tcpClient.Close(); 51 | break; 52 | } 53 | 54 | byte[] allbBytes = ASCIIEncoding.ASCII.GetBytes(str + x); 55 | stream.WriteTimeout = 3000; 56 | stream.Write(allbBytes, 0, allbBytes.Length); 57 | //x++; 58 | //Console.ReadLine(); 59 | Thread.Sleep(1000); 60 | count++; 61 | } 62 | 63 | Console.WriteLine("*** Test null port ***"); 64 | //异常数据测试 65 | 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/TcpClient/TcpClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | ..\build\ 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/TcpServer/Program.cs: -------------------------------------------------------------------------------- 1 | using NSmartProxy; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Net.Sockets; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace TCPTester.Server 12 | { 13 | class Program 14 | { 15 | static void Main(string[] args) 16 | { 17 | Console.WriteLine("*** Tcp Sever ***"); 18 | //int port = int.Parse(args[0]); 19 | int port = 12346; 20 | Console.WriteLine("start listen " + port.ToString()); 21 | TcpListener tcpListener = TcpListener.Create(port); 22 | tcpListener.Start(); 23 | TcpClient client = null; 24 | CancellationTokenSource cts = null; 25 | 26 | // var thread = new Thread(() => 27 | // { 28 | int count = 5; 29 | //while (count > 0) 30 | //{ 31 | client = tcpListener.AcceptTcpClient(); 32 | //client.SetKeepAlive(out _); 33 | 34 | //Task.Run(() => 35 | //{ 36 | var stream = client.GetStream(); 37 | 38 | while (count > 0) 39 | { 40 | byte[] bytes = new byte[4096]; 41 | try 42 | { 43 | cts = new CancellationTokenSource(); 44 | Task result = stream.ReadAsync(bytes, 0, bytes.Length, cts.Token); 45 | result.Wait(cts.Token); 46 | var length = result.Result; 47 | Console.WriteLine("continue..." + length); 48 | Console.WriteLine(ASCIIEncoding.ASCII.GetString(bytes, 0, length).Trim()); 49 | string retMessage = "received++" + ASCIIEncoding.ASCII.GetString(bytes, 0, length).Trim() + "+++"; 50 | byte[] retMessageBytes = ASCIIEncoding.ASCII.GetBytes(retMessage); 51 | stream.Write(retMessageBytes, 0, retMessageBytes.Length); 52 | if (length == 0) { stream.Close(); break; } 53 | } 54 | catch 55 | { 56 | break; 57 | } 58 | count--; 59 | } 60 | 61 | //}); 62 | 63 | //} 64 | Environment.Exit(0); 65 | 66 | //}); 67 | 68 | //thread.Start(); 69 | //while (true) 70 | //{ 71 | // var line = Console.ReadLine(); 72 | // if (line == "stop") 73 | // { 74 | // //client.Close(); 75 | // //cts.Cancel(true); 76 | // TcpClient tc = new TcpClient(); 77 | // tc.Connect("127.0.0.1", 12306); 78 | // tc.Client.Send(new byte[] { 0 }); 79 | // } 80 | //} 81 | 82 | 83 | 84 | } 85 | 86 | public static void test111() 87 | { 88 | 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/TcpServer/TcpServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | ..\build\ 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/TestBed.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29509.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UdpClient", "UdpClient\UdpClient.csproj", "{838D1F04-3729-4A72-BC10-4FC309950E22}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UdpServer", "UdpServer\UdpServer.csproj", "{D078BCA3-F4C1-4734-A790-930891F1B8B9}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpServer", "TcpServer\TcpServer.csproj", "{DDC8D106-A4D8-43F7-BC50-A02EAEEB53A3}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpClient", "TcpClient\TcpClient.csproj", "{55666FC4-4E70-47E1-BC38-0CFC7564876E}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {838D1F04-3729-4A72-BC10-4FC309950E22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {838D1F04-3729-4A72-BC10-4FC309950E22}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {838D1F04-3729-4A72-BC10-4FC309950E22}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {838D1F04-3729-4A72-BC10-4FC309950E22}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {D078BCA3-F4C1-4734-A790-930891F1B8B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {D078BCA3-F4C1-4734-A790-930891F1B8B9}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {D078BCA3-F4C1-4734-A790-930891F1B8B9}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {D078BCA3-F4C1-4734-A790-930891F1B8B9}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {DDC8D106-A4D8-43F7-BC50-A02EAEEB53A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {DDC8D106-A4D8-43F7-BC50-A02EAEEB53A3}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {DDC8D106-A4D8-43F7-BC50-A02EAEEB53A3}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {DDC8D106-A4D8-43F7-BC50-A02EAEEB53A3}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {55666FC4-4E70-47E1-BC38-0CFC7564876E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {55666FC4-4E70-47E1-BC38-0CFC7564876E}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {55666FC4-4E70-47E1-BC38-0CFC7564876E}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {55666FC4-4E70-47E1-BC38-0CFC7564876E}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {4EBF3A7E-72AE-42DC-9536-E338010182F8} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /test/UdpClient/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | using System.Runtime.InteropServices.ComTypes; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ConsoleApp15 9 | { 10 | class Program 11 | { 12 | const int TargetPort = 30001; 13 | 14 | static async Task Main(string[] args) 15 | { 16 | await Task.Delay(2000);//慢点启动,以防服务端还没起来消息就发出去了 17 | Console.WriteLine("*** Udp Client ***"); 18 | UdpClient udpClient = new UdpClient(); 19 | 20 | udpClient.Connect("127.0.0.1", TargetPort); 21 | //udpClient.Connect("127.0.0.1", 9999 ); 22 | _ = ReceiveUdpClientAsync(udpClient); 23 | int count = 5; 24 | while (count > 0) 25 | { 26 | string str = "test"+count; 27 | 28 | if (str == "0") 29 | { 30 | udpClient.Close(); 31 | //udpClient.Connect("127.0.0.1", 9999);关了就没法再连了 必须new 32 | continue; 33 | } 34 | 35 | var bytes = Encoding.ASCII.GetBytes(str); 36 | await udpClient.SendAsync(bytes, bytes.Length); 37 | Console.WriteLine($"发送{str}"); 38 | await Task.Delay(1000); 39 | count--; 40 | } 41 | 42 | 43 | } 44 | 45 | private static async Task ReceiveUdpClientAsync(UdpClient udpClient) 46 | { 47 | while (true) 48 | { 49 | var udpReceiveResult = await udpClient.ReceiveAsync();//如果服务端没起来 这里将会永久阻塞,即使之后起来了也不行 50 | Console.WriteLine("接收到" + Encoding.ASCII.GetString(udpReceiveResult.Buffer)); 51 | } 52 | 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/UdpClient/UdpClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | ..\build\ 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/UdpServer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Sockets; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace UdpServer 7 | { 8 | class Program 9 | { 10 | const int listenPort = 30001; 11 | 12 | static async Task Main(string[] args) 13 | { 14 | Console.WriteLine("*** Udp Sever ***"); 15 | UdpClient udpClient = new UdpClient(listenPort); 16 | //UdpClient udpClient = new UdpClient(9999); 17 | int count = 5; 18 | while (count > 0) 19 | { 20 | var udpReceiveResult = await udpClient.ReceiveAsync(); 21 | var str = Encoding.ASCII.GetString(udpReceiveResult.Buffer); 22 | var receiveStr = Encoding.ASCII.GetBytes("hello" + str); 23 | await udpClient.SendAsync(receiveStr, receiveStr.Length, udpReceiveResult.RemoteEndPoint); 24 | Console.WriteLine($"[{udpReceiveResult.RemoteEndPoint.ToString()}]{str}"); 25 | count--; 26 | } 27 | 28 | //Console.WriteLine("Hello World!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/UdpServer/UdpServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | ..\build\ 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/auto_test.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo *** NSP TEST *** 3 | 4 | set buildPath=%~dp0\build 5 | set testPath=%buildPath%\netcoreapp3.0 6 | set nspClientPath=%buildPath%\nspclient\netcoreapp3.0 7 | set nspServerPath=%buildPath%\nspserver\netcoreapp3.0 8 | 9 | REM BUILD 10 | MSBuild .\TestBed.sln /t:build 11 | dotnet build ..\src\NSmartProxyClient\NSmartProxyClient.csproj 12 | dotnet build ..\src\NSmartProxy.ServerHost\NSmartProxy.ServerHost.csproj 13 | 14 | 15 | rem run nsmartproxy 16 | start "" cmd /c "%nspServerPath%\NSmartProxy.ServerHost.exe" 17 | start "" cmd /c "%nspClientPath%\NSmartProxyClient.exe" 18 | 19 | rem Wait them ready... 20 | powershell Start-Sleep -Seconds 3 21 | 22 | rem appsettings 23 | copy "%buildPath%\_appsettings_server.txt" "%nspServerPath%\appsettings.json" /y 24 | copy "%buildPath%\_appsettings_client.txt" "%nspClientPath%\appsettings.json" /y 25 | 26 | rem start server 27 | start "" cmd /c "%testPath%/TcpServer.exe" 28 | %testPath%/TcpClient.exe 29 | 30 | rem start client 31 | start "" cmd /c "dotnet %testPath%/UdpServer.dll" 32 | dotnet %testPath%/UdpClient.dll 33 | 34 | echo =============================================== 35 | echo TEST ACCOMPLISHeD 36 | pause 37 | rem test service1 TCP 38 | rem test service2 UDP 39 | rem test service3 HTTP1 40 | rem test service4 HTTP2 41 | -------------------------------------------------------------------------------- /theo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/theo.png -------------------------------------------------------------------------------- /wx/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | build-dbg 3 | .DS_Store -------------------------------------------------------------------------------- /wx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(wxNSmartProxyClientGUI LANGUAGES CXX) 4 | 5 | include(FetchContent) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 9 | 10 | set(wxBUILD_SHARED OFF) 11 | 12 | message(STATUS "Fetching wxWidgets...") 13 | 14 | FetchContent_Declare( 15 | wxWidgets 16 | GIT_REPOSITORY https://github.com/wxWidgets/wxWidgets.git 17 | GIT_SHALLOW ON 18 | ) 19 | FetchContent_MakeAvailable(wxWidgets) 20 | #自动收集所有的.cpp .h源文件,不包含子目录 21 | file(GLOB rootdir_files ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/*.h) 22 | 23 | message(rootdir_files: ${rootdir_files}) 24 | set(SRCS ${rootdir_files}) 25 | 26 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SRC_FILES}) 27 | 28 | include_directories(${wxWidgets_SOURCE_DIR}) 29 | 30 | if(APPLE) 31 | # create bundle on apple compiles 32 | add_executable(main MACOSX_BUNDLE ${SRCS}) 33 | 34 | # Set a custom plist file for the app bundle - needed for Mac OS Retina display 35 | set_target_properties(main PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) 36 | else() 37 | # the WIN32 is needed for Windows in order for it to look for WinMain 38 | # instead of the main function. This is ignored on other systems, 39 | # so it works on all platforms 40 | add_executable(main WIN32 ${SRCS} main.exe.manifest) 41 | endif() 42 | 43 | target_link_libraries(main PRIVATE wxcore wxnet) -------------------------------------------------------------------------------- /wx/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | com.lukesdevtutorials.wx_cmake_fetchcontent_template 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundlePackageType 10 | APPL 11 | NSPrincipalClass 12 | NSApplication 13 | NSHighResolutionCapable 14 | 15 | 16 | -------------------------------------------------------------------------------- /wx/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 lszl84 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /wx/MainFrame.cpp: -------------------------------------------------------------------------------- 1 | #include "MainFrame.h" 2 | #include 3 | 4 | MainFrame::MainFrame(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style) 5 | : MainFrame_generated(parent, id, title, pos, size, style) 6 | { 7 | // 事件绑定 8 | Bind(wxEVT_BUTTON, &MainFrame::OnBtnLogin, this, nsp_btnLogin); 9 | Bind(wxEVT_BUTTON, &MainFrame::OnBtnStart, this, nsp_btnStart); 10 | Bind(wxEVT_BUTTON, &MainFrame::OnBtnExit, this, nsp_btnExit); 11 | } 12 | 13 | void MainFrame::OnBtnLogin(wxCommandEvent &event) 14 | { 15 | wxMessageBox("Login"); 16 | } 17 | 18 | void MainFrame::OnBtnStart(wxCommandEvent &event) 19 | { 20 | wxMessageBox("Start"); 21 | } 22 | 23 | void MainFrame::OnBtnExit(wxCommandEvent &event) 24 | { 25 | wxMessageBox("Exit"); 26 | } 27 | 28 | MainFrame::~MainFrame() 29 | { 30 | } -------------------------------------------------------------------------------- /wx/MainFrame.generated.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////// 2 | // C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6) 3 | // http://www.wxformbuilder.org/ 4 | // 5 | // PLEASE DO *NOT* EDIT THIS FILE! 6 | /////////////////////////////////////////////////////////////////////////// 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | /////////////////////////////////////////////////////////////////////////// 35 | 36 | /////////////////////////////////////////////////////////////////////////////// 37 | /// Class MainFrame_generated 38 | /////////////////////////////////////////////////////////////////////////////// 39 | class MainFrame_generated : public wxFrame 40 | { 41 | private: 42 | 43 | protected: 44 | enum 45 | { 46 | nsp_btnLogin = 6000, 47 | nsp_btnStart, 48 | nsp_btnExit, 49 | }; 50 | 51 | wxNotebook* m_tabctrlMain; 52 | wxPanel* m_panelApp; 53 | wxStaticText* m_staticText1; 54 | wxTextCtrl* m_textCtrl1; 55 | wxStaticText* m_staticText2; 56 | wxTextCtrl* m_textCtrl2; 57 | wxButton* m_btnTest; 58 | wxPanel* m_panel8; 59 | wxWrapSizer* wSizer3; 60 | wxButton* m_btnAddNode; 61 | wxButton* m_btnDelNode; 62 | wxButton* m_btnDupNode; 63 | wxButton* m_btnRestoreNodes; 64 | wxButton* m_btnSaveNodes; 65 | wxPanel* m_panel10; 66 | wxPanel* m_panel81; 67 | wxStaticText* m_staticText3; 68 | wxChoice* m_choice1; 69 | wxStaticText* m_staticText5; 70 | wxTextCtrl* m_textCtrl5; 71 | wxStaticText* m_staticText6; 72 | wxTextCtrl* m_textCtrl6; 73 | wxStaticText* m_staticText7; 74 | wxTextCtrl* m_textCtrl7; 75 | wxStaticText* m_staticText8; 76 | wxTextCtrl* m_textCtrl8; 77 | wxStaticText* m_staticText9; 78 | wxTextCtrl* m_textCtrl9; 79 | wxStaticText* m_staticText10; 80 | wxCheckBox* m_checkBox1; 81 | wxCheckBox* m_checkBox2; 82 | wxPanel* m_panelLog; 83 | wxTextCtrl* m_textCtrl4; 84 | wxPanel* m_panel6; 85 | wxPanel* m_panel7; 86 | wxPanel* m_pnlBottomBtns; 87 | wxButton* m_btnLogin; 88 | wxButton* m_btnStart; 89 | wxButton* m_btnExit; 90 | 91 | public: 92 | wxListBox* m_listBox1; 93 | 94 | MainFrame_generated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("NSmartProxyClient配置对话框"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 840,600 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); 95 | 96 | ~MainFrame_generated(); 97 | 98 | }; 99 | 100 | -------------------------------------------------------------------------------- /wx/MainFrame.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MainFrame.generated.h" 3 | 4 | // 继承自MainFrame_generated 5 | class MainFrame : public MainFrame_generated 6 | { 7 | public: 8 | MainFrame(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style); 9 | ~MainFrame(); 10 | 11 | private: 12 | void OnBtnLogin(wxCommandEvent &event); 13 | void OnBtnStart(wxCommandEvent &event); 14 | void OnBtnExit(wxCommandEvent &event); 15 | }; 16 | -------------------------------------------------------------------------------- /wx/README.md: -------------------------------------------------------------------------------- 1 | ## Project Overview 2 | 3 | Integrate wxWidgets and nsmartproxy to create a C++ project with a graphical user interface and proxy functionality!## System Requirements 4 | 5 | To get started with this project, ensure you have the following tools and libraries: 6 | 7 | - **CMake (Version 3.14 or later):** Essential for building and managing the project files. 8 | - **C++ Compiler:** Compatible with Clang, GCC, or MSVC. Choose one based on your development environment. 9 | - **GTK3 Development Libraries (for Linux users):** Necessary for GUI development on Linux platforms. 10 | 11 | ## Building the Project 12 | 13 | # Debug 14 | 15 | Follow these steps to build the project: 16 | 17 | 1. **Create a build directory & configure the build:**2. **Build the project:**This will create a `build` directory and compile all necessary artifacts there. The main executable will be located in `build/`. 18 | 19 | # Release 20 | 21 | For release build use `--config Release` on Windows:Artifacts for both configurations will be generated in the `build` directory. 22 | 23 | On Mac or Linux you'll need to maintain two build trees:## License 24 | 25 | MIT License. Can be used in closed-source commercial products. -------------------------------------------------------------------------------- /wx/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmoonlight/NSmartProxy/eda706dc5ece0dbd247a712b26e66d4e9ce7f034/wx/main.cpp -------------------------------------------------------------------------------- /wx/main.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | PerMonitorV2 7 | 8 | 9 | --------------------------------------------------------------------------------