diff --git a/driver/OemVista.inf b/driver/OemVista.inf index d92e255..628a215 100644 --- a/driver/OemVista.inf +++ b/driver/OemVista.inf @@ -1,191 +1,191 @@ -; **************************************************************************** -; * Copyright (C) 2002-2014 OpenVPN Technologies, Inc. * -; * This program is free software; you can redistribute it and/or modify * -; * it under the terms of the GNU General Public License version 2 * -; * as published by the Free Software Foundation. * -; **************************************************************************** - -; SYNTAX CHECKER -; cd \WINDDK\3790\tools\chkinf -; chkinf c:\src\openvpn\tap-win32\i386\oemvista.inf -; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm - -; INSTALL/REMOVE DRIVER -; tapinstall install OemVista.inf tapoas -; tapinstall update OemVista.inf tapoas -; tapinstall remove tapoas - -;********************************************************* -; Note to Developers: -; -; If you are bundling the TAP-Windows driver with your app, -; you should try to rename it in such a way that it will -; not collide with other instances of TAP-Windows defined -; by other apps. Multiple versions of the TAP-Windows -; driver, each installed by different apps, can coexist -; on the same machine if you follow these guidelines. -; NOTE: these instructions assume you are editing the -; generated OemWin2k.inf file, not the source -; OemWin2k.inf.in file which is preprocessed by winconfig -; and uses macro definitions from settings.in. -; -; (1) Rename all tapXXXX instances in this file to -; something different (use at least 5 characters -; for this name!) -; (2) Change the "!define TAP" definition in openvpn.nsi -; to match what you changed tapXXXX to. -; (3) Change TARGETNAME in SOURCES to match what you -; changed tapXXXX to. -; (4) Change TAP_COMPONENT_ID in common.h to match what -; you changed tapXXXX to. -; (5) Change SZDEPENDENCIES in service.h to match what -; you changed tapXXXX to. -; (6) Change DeviceDescription and Provider strings. -; (7) Change PRODUCT_TAP_WIN_DEVICE_DESCRIPTION in constants.h to what you -; set DeviceDescription to. -; -;********************************************************* - -[Version] - Signature = "$Windows NT$" - CatalogFile = tap0901.cat - ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} - Provider = %Provider% - Class = Net - -; This version number should match the version -; number given in SOURCES. - DriverVer=04/21/2016,9.00.00.21 - -[Strings] - DeviceDescription = "TAP-Windows Adapter V9" - Provider = "TAP-Windows Provider V9" - -;---------------------------------------------------------------- -; Manufacturer + Product Section (Done) -;---------------------------------------------------------------- -[Manufacturer] - %Provider% = tap0901, NTamd64 - -[tap0901.NTamd64] - %DeviceDescription% = tap0901.ndi, root\tap0901 ; Root enumerated - %DeviceDescription% = tap0901.ndi, tap0901 ; Legacy - -;--------------------------------------------------------------- -; Driver Section (Done) -;--------------------------------------------------------------- - -;----------------- Characteristics ------------ -; NCF_PHYSICAL = 0x04 -; NCF_VIRTUAL = 0x01 -; NCF_SOFTWARE_ENUMERATED = 0x02 -; NCF_HIDDEN = 0x08 -; NCF_NO_SERVICE = 0x10 -; NCF_HAS_UI = 0x80 -;----------------- Characteristics ------------ - -[tap0901.ndi] - CopyFiles = tap0901.driver, tap0901.files - AddReg = tap0901.reg - AddReg = tap0901.params.reg - Characteristics = - *IfType = 0x6 ; IF_TYPE_ETHERNET_CSMACD - *MediaType = 0x0 ; NdisMedium802_3 - *PhysicalMediaType = 14 ; NdisPhysicalMedium802_3 - -[tap0901.ndi.Services] - AddService = tap0901, 2, tap0901.service - -[tap0901.reg] - HKR, Ndi, Service, 0, "tap0901" - HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" - HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" - HKR, , Manufacturer, 0, "%Provider%" - HKR, , ProductName, 0, "%DeviceDescription%" - -[tap0901.params.reg] - HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" - HKR, Ndi\params\MTU, Type, 0, "int" - HKR, Ndi\params\MTU, Default, 0, "1500" - HKR, Ndi\params\MTU, Optional, 0, "0" - HKR, Ndi\params\MTU, Min, 0, "100" - HKR, Ndi\params\MTU, Max, 0, "1500" - HKR, Ndi\params\MTU, Step, 0, "1" - HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" - HKR, Ndi\params\MediaStatus, Type, 0, "enum" - HKR, Ndi\params\MediaStatus, Default, 0, "0" - HKR, Ndi\params\MediaStatus, Optional, 0, "0" - HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" - HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" - HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" - HKR, Ndi\params\MAC, Type, 0, "edit" - HKR, Ndi\params\MAC, Optional, 0, "1" - HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" - HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" - HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" - HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" - HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" - HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" - -;---------------------------------------------------------------- -; Service Section -;---------------------------------------------------------------- - -;---------- Service Type ------------- -; SERVICE_KERNEL_DRIVER = 0x01 -; SERVICE_WIN32_OWN_PROCESS = 0x10 -;---------- Service Type ------------- - -;---------- Start Mode --------------- -; SERVICE_BOOT_START = 0x0 -; SERVICE_SYSTEM_START = 0x1 -; SERVICE_AUTO_START = 0x2 -; SERVICE_DEMAND_START = 0x3 -; SERVICE_DISABLED = 0x4 -;---------- Start Mode --------------- - -[tap0901.service] - DisplayName = %DeviceDescription% - ServiceType = 1 - StartType = 3 - ErrorControl = 1 - LoadOrderGroup = NDIS - ServiceBinary = %12%\tap0901.sys - -;----------------------------------------------------------------- -; File Installation -;----------------------------------------------------------------- - -;----------------- Copy Flags ------------ -; COPYFLG_NOSKIP = 0x02 -; COPYFLG_NOVERSIONCHECK = 0x04 -;----------------- Copy Flags ------------ - -; SourceDisksNames -; diskid = description[, [tagfile] [, , subdir]] -; 1 = "Intel Driver Disk 1",e100bex.sys,, - -[SourceDisksNames] - 1 = %DeviceDescription%, tap0901.sys - -; SourceDisksFiles -; filename_on_source = diskID[, [subdir][, size]] -; e100bex.sys = 1,, ; on distribution disk 1 - -[SourceDisksFiles] -tap0901.sys = 1 - -[DestinationDirs] - tap0901.files = 11 - tap0901.driver = 12 - -[tap0901.files] -; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK -; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK - -[tap0901.driver] - tap0901.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK - -;--------------------------------------------------------------- -; End -;--------------------------------------------------------------- +; **************************************************************************** +; * Copyright (C) 2002-2014 OpenVPN Technologies, Inc. * +; * This program is free software; you can redistribute it and/or modify * +; * it under the terms of the GNU General Public License version 2 * +; * as published by the Free Software Foundation. * +; **************************************************************************** + +; SYNTAX CHECKER +; cd \WINDDK\3790\tools\chkinf +; chkinf c:\src\openvpn\tap-win32\i386\oemvista.inf +; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm + +; INSTALL/REMOVE DRIVER +; tapinstall install OemVista.inf tapoas +; tapinstall update OemVista.inf tapoas +; tapinstall remove tapoas + +;********************************************************* +; Note to Developers: +; +; If you are bundling the TAP-Windows driver with your app, +; you should try to rename it in such a way that it will +; not collide with other instances of TAP-Windows defined +; by other apps. Multiple versions of the TAP-Windows +; driver, each installed by different apps, can coexist +; on the same machine if you follow these guidelines. +; NOTE: these instructions assume you are editing the +; generated OemWin2k.inf file, not the source +; OemWin2k.inf.in file which is preprocessed by winconfig +; and uses macro definitions from settings.in. +; +; (1) Rename all tapXXXX instances in this file to +; something different (use at least 5 characters +; for this name!) +; (2) Change the "!define TAP" definition in openvpn.nsi +; to match what you changed tapXXXX to. +; (3) Change TARGETNAME in SOURCES to match what you +; changed tapXXXX to. +; (4) Change TAP_COMPONENT_ID in common.h to match what +; you changed tapXXXX to. +; (5) Change SZDEPENDENCIES in service.h to match what +; you changed tapXXXX to. +; (6) Change DeviceDescription and Provider strings. +; (7) Change PRODUCT_TAP_WIN_DEVICE_DESCRIPTION in constants.h to what you +; set DeviceDescription to. +; +;********************************************************* + +[Version] + Signature = "$Windows NT$" + CatalogFile = tap0901.cat + ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} + Provider = %Provider% + Class = Net + +; This version number should match the version +; number given in SOURCES. + DriverVer=04/21/2016,9.00.00.21 + +[Strings] + DeviceDescription = "TAP-Windows Adapter V9" + Provider = "TAP-Windows Provider V9" + +;---------------------------------------------------------------- +; Manufacturer + Product Section (Done) +;---------------------------------------------------------------- +[Manufacturer] + %Provider% = tap0901, NTamd64 + +[tap0901.NTamd64] + %DeviceDescription% = tap0901.ndi, root\tap0901 ; Root enumerated + %DeviceDescription% = tap0901.ndi, tap0901 ; Legacy + +;--------------------------------------------------------------- +; Driver Section (Done) +;--------------------------------------------------------------- + +;----------------- Characteristics ------------ +; NCF_PHYSICAL = 0x04 +; NCF_VIRTUAL = 0x01 +; NCF_SOFTWARE_ENUMERATED = 0x02 +; NCF_HIDDEN = 0x08 +; NCF_NO_SERVICE = 0x10 +; NCF_HAS_UI = 0x80 +;----------------- Characteristics ------------ + +[tap0901.ndi] + CopyFiles = tap0901.driver, tap0901.files + AddReg = tap0901.reg + AddReg = tap0901.params.reg + Characteristics = + *IfType = 0x6 ; IF_TYPE_ETHERNET_CSMACD + *MediaType = 0x0 ; NdisMedium802_3 + *PhysicalMediaType = 14 ; NdisPhysicalMedium802_3 + +[tap0901.ndi.Services] + AddService = tap0901, 2, tap0901.service + +[tap0901.reg] + HKR, Ndi, Service, 0, "tap0901" + HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" + HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + HKR, , Manufacturer, 0, "%Provider%" + HKR, , ProductName, 0, "%DeviceDescription%" + +[tap0901.params.reg] + HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" + HKR, Ndi\params\MTU, Type, 0, "int" + HKR, Ndi\params\MTU, Default, 0, "1500" + HKR, Ndi\params\MTU, Optional, 0, "0" + HKR, Ndi\params\MTU, Min, 0, "100" + HKR, Ndi\params\MTU, Max, 0, "1500" + HKR, Ndi\params\MTU, Step, 0, "1" + HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" + HKR, Ndi\params\MediaStatus, Type, 0, "enum" + HKR, Ndi\params\MediaStatus, Default, 0, "0" + HKR, Ndi\params\MediaStatus, Optional, 0, "0" + HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" + HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" + HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" + HKR, Ndi\params\MAC, Type, 0, "edit" + HKR, Ndi\params\MAC, Optional, 0, "1" + HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" + HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" + HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" + HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" + HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" + HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" + +;---------------------------------------------------------------- +; Service Section +;---------------------------------------------------------------- + +;---------- Service Type ------------- +; SERVICE_KERNEL_DRIVER = 0x01 +; SERVICE_WIN32_OWN_PROCESS = 0x10 +;---------- Service Type ------------- + +;---------- Start Mode --------------- +; SERVICE_BOOT_START = 0x0 +; SERVICE_SYSTEM_START = 0x1 +; SERVICE_AUTO_START = 0x2 +; SERVICE_DEMAND_START = 0x3 +; SERVICE_DISABLED = 0x4 +;---------- Start Mode --------------- + +[tap0901.service] + DisplayName = %DeviceDescription% + ServiceType = 1 + StartType = 3 + ErrorControl = 1 + LoadOrderGroup = NDIS + ServiceBinary = %12%\tap0901.sys + +;----------------------------------------------------------------- +; File Installation +;----------------------------------------------------------------- + +;----------------- Copy Flags ------------ +; COPYFLG_NOSKIP = 0x02 +; COPYFLG_NOVERSIONCHECK = 0x04 +;----------------- Copy Flags ------------ + +; SourceDisksNames +; diskid = description[, [tagfile] [, , subdir]] +; 1 = "Intel Driver Disk 1",e100bex.sys,, + +[SourceDisksNames] + 1 = %DeviceDescription%, tap0901.sys + +; SourceDisksFiles +; filename_on_source = diskID[, [subdir][, size]] +; e100bex.sys = 1,, ; on distribution disk 1 + +[SourceDisksFiles] +tap0901.sys = 1 + +[DestinationDirs] + tap0901.files = 11 + tap0901.driver = 12 + +[tap0901.files] +; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK +; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +[tap0901.driver] + tap0901.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +;--------------------------------------------------------------- +; End +;--------------------------------------------------------------- diff --git a/driver/OemWin2k.inf b/driver/OemWin2k.inf new file mode 100644 index 0000000..3a0398c --- /dev/null +++ b/driver/OemWin2k.inf @@ -0,0 +1,187 @@ +; **************************************************************************** +; * Copyright (C) 2002-2008 OpenVPN Technologies, Inc. * +; * This program is free software; you can redistribute it and/or modify * +; * it under the terms of the GNU General Public License version 2 * +; * as published by the Free Software Foundation. * +; **************************************************************************** + +; SYNTAX CHECKER +; cd \WINDDK\3790\tools\chkinf +; chkinf c:\src\openvpn\tap-win32\i386\oemwin2k.inf +; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm + +; INSTALL/REMOVE DRIVER +; tapinstall install OemWin2k.inf TAP0901 +; tapinstall update OemWin2k.inf TAP0901 +; tapinstall remove TAP0901 + +;********************************************************* +; Note to Developers: +; +; If you are bundling the TAP-Win32 driver with your app, +; you should try to rename it in such a way that it will +; not collide with other instances of TAP-Win32 defined +; by other apps. Multiple versions of the TAP-Win32 +; driver, each installed by different apps, can coexist +; on the same machine if you follow these guidelines. +; NOTE: these instructions assume you are editing the +; generated OemWin2k.inf file, not the source +; OemWin2k.inf.in file which is preprocessed by winconfig +; and uses macro definitions from settings.in. +; +; (1) Rename all tapXXXX instances in this file to +; something different (use at least 5 characters +; for this name!) +; (2) Change the "!define TAP" definition in openvpn.nsi +; to match what you changed tapXXXX to. +; (3) Change TARGETNAME in SOURCES to match what you +; changed tapXXXX to. +; (4) Change TAP_COMPONENT_ID in common.h to match what +; you changed tapXXXX to. +; (5) Change SZDEPENDENCIES in service.h to match what +; you changed tapXXXX to. +; (6) Change DeviceDescription and Provider strings. +; (7) Change PRODUCT_STRING in constants.h to what you +; set DeviceDescription to. +; +;********************************************************* + +[Version] + Signature = "$Windows NT$" + CatalogFile = tap0901.cat + ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} + Provider = %Provider% + Class = Net + +; This version number should match the version +; number given in SOURCES. + DriverVer=01/22/2008,9.00.00.4 + +[Strings] + DeviceDescription = "TAP-Win32 Adapter V9" + Provider = "TAP-Win32 Provider V9" + +;---------------------------------------------------------------- +; Manufacturer + Product Section (Done) +;---------------------------------------------------------------- +[Manufacturer] + %Provider% = tap0901, NTamd64 + +[tap0901.NTamd64] + %DeviceDescription% = tap0901.ndi, tap0901 + +;--------------------------------------------------------------- +; Driver Section (Done) +;--------------------------------------------------------------- + +;----------------- Characteristics ------------ +; NCF_PHYSICAL = 0x04 +; NCF_VIRTUAL = 0x01 +; NCF_SOFTWARE_ENUMERATED = 0x02 +; NCF_HIDDEN = 0x08 +; NCF_NO_SERVICE = 0x10 +; NCF_HAS_UI = 0x80 +;----------------- Characteristics ------------ + +[tap0901.ndi] + CopyFiles = tap0901.driver, tap0901.files + AddReg = tap0901.reg + AddReg = tap0901.params.reg + Characteristics = 0x81 + +[tap0901.ndi.Services] + AddService = tap0901, 2, tap0901.service + +[tap0901.reg] + HKR, Ndi, Service, 0, "tap0901" + HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" + HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + HKR, , Manufacturer, 0, "%Provider%" + HKR, , ProductName, 0, "%DeviceDescription%" + +[tap0901.params.reg] + HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" + HKR, Ndi\params\MTU, Type, 0, "int" + HKR, Ndi\params\MTU, Default, 0, "1500" + HKR, Ndi\params\MTU, Optional, 0, "0" + HKR, Ndi\params\MTU, Min, 0, "100" + HKR, Ndi\params\MTU, Max, 0, "1500" + HKR, Ndi\params\MTU, Step, 0, "1" + HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" + HKR, Ndi\params\MediaStatus, Type, 0, "enum" + HKR, Ndi\params\MediaStatus, Default, 0, "0" + HKR, Ndi\params\MediaStatus, Optional, 0, "0" + HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" + HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" + HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" + HKR, Ndi\params\MAC, Type, 0, "edit" + HKR, Ndi\params\MAC, Optional, 0, "1" + HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" + HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" + HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" + HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" + HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" + HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" + +;---------------------------------------------------------------- +; Service Section +;---------------------------------------------------------------- + +;---------- Service Type ------------- +; SERVICE_KERNEL_DRIVER = 0x01 +; SERVICE_WIN32_OWN_PROCESS = 0x10 +;---------- Service Type ------------- + +;---------- Start Mode --------------- +; SERVICE_BOOT_START = 0x0 +; SERVICE_SYSTEM_START = 0x1 +; SERVICE_AUTO_START = 0x2 +; SERVICE_DEMAND_START = 0x3 +; SERVICE_DISABLED = 0x4 +;---------- Start Mode --------------- + +[tap0901.service] + DisplayName = %DeviceDescription% + ServiceType = 1 + StartType = 3 + ErrorControl = 1 + LoadOrderGroup = NDIS + ServiceBinary = %12%\tap0901.sys + +;----------------------------------------------------------------- +; File Installation +;----------------------------------------------------------------- + +;----------------- Copy Flags ------------ +; COPYFLG_NOSKIP = 0x02 +; COPYFLG_NOVERSIONCHECK = 0x04 +;----------------- Copy Flags ------------ + +; SourceDisksNames +; diskid = description[, [tagfile] [, , subdir]] +; 1 = "Intel Driver Disk 1",e100bex.sys,, + +[SourceDisksNames] + 1 = %DeviceDescription%, tap0901.sys + +; SourceDisksFiles +; filename_on_source = diskID[, [subdir][, size]] +; e100bex.sys = 1,, ; on distribution disk 1 + +[SourceDisksFiles] +tap0901.sys = 1 + +[DestinationDirs] + tap0901.files = 11 + tap0901.driver = 12 + +[tap0901.files] +; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK +; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +[tap0901.driver] + tap0901.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK + +;--------------------------------------------------------------- +; End +;--------------------------------------------------------------- diff --git a/driver/tapinstall.exe b/driver/tapinstall.exe index a1ebb9f..b18b26c 100644 Binary files a/driver/tapinstall.exe and b/driver/tapinstall.exe differ diff --git a/test/filters/TCP.ts b/test/filters/TCP.ts index 08a677f..4cb266c 100644 --- a/test/filters/TCP.ts +++ b/test/filters/TCP.ts @@ -5,10 +5,10 @@ import { IpProtocol, EthernetType, } from "../PacketsStruct"; -import ShadowsocksTcpClient from "../shadowsocks/ShadowsocksTcpClient"; import TcpPacketFormatter from "../formatters/TcpPacketFormatter"; import * as EventEmitter from "events"; +const TCP_LOG_ENABLE = false; // tslint:disable-next-line:interface-name interface TcpConnection { ipversion: EthernetType; @@ -35,10 +35,15 @@ enum TcpConnectionState { Closed, } -class TcpServerSession extends EventEmitter { +/** + * TcpServerSession包含的事件 + * connected : 已经建立连接 + * read : 读取到数据包 + * closed : 关闭连接 + */ +export class TcpServerSession extends EventEmitter { private state: TcpConnectionState; - private shadowsocks: ShadowsocksTcpClient; private currentIdNum: number; private currentSeqNum: number = 0; @@ -51,28 +56,22 @@ class TcpServerSession extends EventEmitter { private routers: Array<(data: Buffer, tcpPacket: TcpPacket) => void> = []; - constructor( - public connection: TcpConnection, - private nativeWrite: (data: Buffer) => void) { - + constructor(public connection: TcpConnection, + private nativeWrite: (data: Buffer) => void, + ) { super(); + this.setMaxListeners(1); this.state = TcpConnectionState.HandShake; this.currentIdNum = 100; - this.routers[TcpConnectionState.HandShake] = this.tcpHandshark.bind(this); - this.routers[TcpConnectionState.HandShake_ACK] = this.tcpHandshark.bind(this); - this.routers[TcpConnectionState.Data] = this.tcpClientData.bind(this); - this.routers[TcpConnectionState.RemoteCloseWating] = this.tcpClientRequestToClose.bind(this); - this.routers[TcpConnectionState.RemoteCloseWating_1] = this.tcpClientRequestToClose.bind(this); - this.routers[TcpConnectionState.LocalCloseWating] = this.tcpShadowsocksClosed.bind(this); - this.routers[TcpConnectionState.LocalCloseWating_1] = this.tcpShadowsocksClosed.bind(this); - this.shadowsocks = new ShadowsocksTcpClient( - Config.get("ShadowsocksTcpHost"), - Config.get("ShadowsocksTcpPort"), - Config.get("ShadowsocksTcpPasswd"), - Config.get("ShadowsocksTcpMethod"), - ); + this.routers[TcpConnectionState.HandShake] = this.handSharkFSM.bind(this); + this.routers[TcpConnectionState.HandShake_ACK] = this.handSharkFSM.bind(this); + this.routers[TcpConnectionState.Data] = this.dataFSM.bind(this); + this.routers[TcpConnectionState.RemoteCloseWating] = this.closeFSM.bind(this); + this.routers[TcpConnectionState.RemoteCloseWating_1] = this.closeFSM.bind(this); + this.routers[TcpConnectionState.LocalCloseWating] = this.closeFSM.bind(this); + this.routers[TcpConnectionState.LocalCloseWating_1] = this.closeFSM.bind(this); } public dataRouter(data: Buffer, tcpPacket: TcpPacket) { @@ -90,7 +89,7 @@ class TcpServerSession extends EventEmitter { } } - public tcpHandshark(data: Buffer, tcpPacket: TcpPacket) { + private handSharkFSM(data: Buffer, tcpPacket: TcpPacket){ if (this.state === TcpConnectionState.HandShake) { if (!tcpPacket.SYN) { return; @@ -109,12 +108,11 @@ class TcpServerSession extends EventEmitter { const tcpAckpacket: Buffer = TcpPacketFormatter.build(ack); this.nativeWrite(tcpAckpacket); this.state = TcpConnectionState.HandShake_ACK; - this.shadowsocks.connect(this.connection.ipversion === EthernetType.IPv4, this.connection.localIp, this.connection.localPort); - this.shadowsocks.on("data", this.tcpShadowsocksData.bind(this)); - this.shadowsocks.on("disconnected", this.tcpShadowsocksClosed.bind(this)); + if(TCP_LOG_ENABLE)console.log("handshark") + this.emit('connected'); return; } - + if (this.state === TcpConnectionState.HandShake_ACK) { if (tcpPacket.acknowledgmentNumber !== this.currentSeqNum + 1) { return; @@ -123,11 +121,15 @@ class TcpServerSession extends EventEmitter { this.currentAckNum = tcpPacket.sequenceNumber; this.currentSeqNum = tcpPacket.acknowledgmentNumber; this.currentWindowSize = tcpPacket.window; + if(TCP_LOG_ENABLE)console.log("handshark ack") return; } } - public tcpClientData(data: Buffer, tcpPacket: TcpPacket) { + private dataFSM(data: Buffer, tcpPacket: TcpPacket) { + if(this.state !== TcpConnectionState.Data){ + return; + } if (tcpPacket.FIN) { this.state = TcpConnectionState.RemoteCloseWating; this.dataRouter(data, tcpPacket); @@ -149,20 +151,34 @@ class TcpServerSession extends EventEmitter { ack = Object.assign(this.buildBaseTcpPacket(), ack); const tcpAckpacket: Buffer = TcpPacketFormatter.build(ack); this.nativeWrite(tcpAckpacket); - this.shadowsocks.write(tcpPacket.payload); + // if(TCP_LOG_ENABLE)console.log("recive data") + this.emit("read",tcpPacket.payload) } /* 只接受最新的ack包作为更新窗口大小 */ if (tcpPacket.acknowledgmentNumber === this.currentSeqNum) { this.currentWindowSize = tcpPacket.window; - this.tcpShadowsocksData(); } - - // console.log(this.currentSeqNum, this.currentAckNum, this.currentWindowSize); } - // TcpConnectionState.RemoteCloseWating - public tcpClientRequestToClose(data: Buffer, tcpPacket: TcpPacket) { + private closeFSM(data: Buffer, tcpPacket: TcpPacket) { + + if (this.state === TcpConnectionState.LocalCloseWating_1 && tcpPacket.FIN && tcpPacket.ACK) { + this.currentSeqNum = tcpPacket.acknowledgmentNumber; + this.currentAckNum = tcpPacket.sequenceNumber + 1; + let fin: TcpPacket = { + sequenceNumber: this.currentSeqNum, + acknowledgmentNumber: this.currentAckNum, + totalLength: 40, + ACK: true, + }; + fin = Object.assign(this.buildBaseTcpPacket(), fin); + const tcpFinPacket: Buffer = TcpPacketFormatter.build(fin); + this.nativeWrite(tcpFinPacket); + this.state = TcpConnectionState.Closed; + this.emit("closed"); + } + if (this.state === TcpConnectionState.RemoteCloseWating) { this.currentSeqNum = tcpPacket.acknowledgmentNumber; this.currentAckNum = tcpPacket.sequenceNumber + 1; @@ -175,8 +191,6 @@ class TcpServerSession extends EventEmitter { }; fin = Object.assign(this.buildBaseTcpPacket(), fin); const tcpFinPacket: Buffer = TcpPacketFormatter.build(fin); - this.shadowsocks.removeAllListeners(); - this.shadowsocks.disconnect(); this.sendingBuffers = []; this.nativeWrite(tcpFinPacket); this.state = TcpConnectionState.RemoteCloseWating_1; @@ -190,19 +204,18 @@ class TcpServerSession extends EventEmitter { } } - public tcpShadowsocksData(data?: Buffer) { + public write(data?: Buffer) { + if(TCP_LOG_ENABLE)console.log(`tcp write current state is ${this.state == TcpConnectionState.Data ? "data" : "not data"}`); if (this.state !== TcpConnectionState.Data) { return; } if (data !== undefined) { this.sendingBuffers = this.sendingBuffers.concat(this.slicePacket(data, 1446)); } - this.shadowsocks.pause(true); if (this.currentWindowSize <= 0) { return; } if (this.sendingBuffers.length === 0) { - this.shadowsocks.pause(false); return; } @@ -212,7 +225,7 @@ class TcpServerSession extends EventEmitter { this.sendingBuffers.shift(); this.currentWindowSize = this.currentWindowSize - waitingBuffer.length; this.sendDataPacket(waitingBuffer); - this.tcpShadowsocksData(); + this.write(); } else { const smallerData: Buffer = waitingBuffer.slice(0, this.currentWindowSize); this.sendingBuffers[0] = waitingBuffer.slice(this.currentWindowSize); @@ -221,25 +234,9 @@ class TcpServerSession extends EventEmitter { } } - public sendDataPacket(data: Buffer, log: boolean = false) { - let dataPacket: TcpPacket = { - sequenceNumber: this.currentSeqNum, - acknowledgmentNumber: this.currentAckNum, - ACK: true, - PSH: true, - payload: data, - }; - dataPacket = Object.assign(this.buildBaseTcpPacket(data.length), dataPacket); - this.currentSeqNum = dataPacket.sequenceNumber + dataPacket.payload.length; - const fullPacket = TcpPacketFormatter.build(dataPacket); - this.nativeWrite(fullPacket); - } - - public tcpShadowsocksClosed(data: Buffer, tcpPacket: TcpPacket) { - + public close(){ if (this.state === TcpConnectionState.Data) { this.sendingBuffers = []; - this.shadowsocks.removeAllListeners(); this.state = TcpConnectionState.LocalCloseWating; let fin: TcpPacket = { sequenceNumber: this.currentSeqNum, @@ -254,29 +251,26 @@ class TcpServerSession extends EventEmitter { this.state = TcpConnectionState.LocalCloseWating_1; return; } + } - if (this.state === TcpConnectionState.LocalCloseWating_1 && tcpPacket.FIN && tcpPacket.ACK) { - this.currentSeqNum = tcpPacket.acknowledgmentNumber; - this.currentAckNum = tcpPacket.sequenceNumber + 1; - let fin: TcpPacket = { - sequenceNumber: this.currentSeqNum, - acknowledgmentNumber: this.currentAckNum, - totalLength: 40, - ACK: true, - }; - fin = Object.assign(this.buildBaseTcpPacket(), fin); - const tcpFinPacket: Buffer = TcpPacketFormatter.build(fin); - this.nativeWrite(tcpFinPacket); - this.state = TcpConnectionState.Closed; - this.emit("closed"); - } + public sendDataPacket(data: Buffer, log: boolean = false) { + let dataPacket: TcpPacket = { + sequenceNumber: this.currentSeqNum, + acknowledgmentNumber: this.currentAckNum, + ACK: true, + PSH: true, + payload: data, + }; + dataPacket = Object.assign(this.buildBaseTcpPacket(data.length), dataPacket); + this.currentSeqNum = dataPacket.sequenceNumber + dataPacket.payload.length; + const fullPacket = TcpPacketFormatter.build(dataPacket); + this.nativeWrite(fullPacket); } public tcpRst(data: Buffer, tcpPacket: TcpPacket) { this.sendingBuffers = []; - this.shadowsocks.removeAllListeners(); - this.shadowsocks.destroy(); this.state = TcpConnectionState.Closed; + if(TCP_LOG_ENABLE)console.log("close") this.emit("closed"); } @@ -347,12 +341,70 @@ class TcpServerSession extends EventEmitter { const connections = new Map(); -export default function(data: Buffer, write: (data: Buffer) => void, next: () => void) { +export class TcpStack extends EventEmitter{ + public connections = new Map(); + constructor( + private output:(data:Buffer)=>void, + ){ + super(); + this.setMaxListeners(1); + } + + public input(data:Buffer){ + /** 跳过非tcp协议的数据包处理 */ + if (PacketUtils.isIPv4(data)) { + if (!PacketUtils.isTCP(data)) { + return; + } + } else if (PacketUtils.isIPv6(data)) { + if (!PacketUtils.isTCPForIpv6(data)) { + return; + } + } else { + return; + } + + const tcpPacket: TcpPacket = TcpPacketFormatter.format(data); + const tcpConnectionId: string = PacketUtils.getConnectionId(tcpPacket); + + let session = connections.get(tcpConnectionId); + if (session === undefined || session == null) { + session = new TcpServerSession({ + ipversion: tcpPacket.version === 4 ? EthernetType.IPv4 : EthernetType.IPv6, + localAddress: tcpPacket.sourceAddress, + targetAddress: tcpPacket.destinaltionAddress, + localIp: tcpPacket.destinationIp, + targetIp: tcpPacket.sourceIp, + localPort: tcpPacket.destinationPort, + targetPort: tcpPacket.sourcePort, + localReceiveWindow: 65535, + targetReceiveWindow: tcpPacket.window, + }, this.output); + session.once("closed", () => { + delete connections[tcpConnectionId]; + // if(TCP_LOG_ENABLE)console.log("bye bye", PacketUtils.ipAddressToString(tcpPacket.destinationIp), "source port", session.connection.targetPort); + }); + connections.set(tcpConnectionId, session); + if(TCP_LOG_ENABLE)console.log("got new session") + // if(TCP_LOG_ENABLE)console.log("connect", PacketUtils.ipAddressToString(tcpPacket.destinationIp), "source port", tcpPacket.sourcePort); + session.once("connected",()=>{ + this.emit("accept",session); + }) + } + session.dataRouter(data, tcpPacket); + } +} + +export default function (data: Buffer, write: (data: Buffer) => void, next: () => void) { if (PacketUtils.isIPv4(data)) { - if (!PacketUtils.isTCP(data)) { return next(); } + if (!PacketUtils.isTCP(data)) { + return next(); + } } else if (PacketUtils.isIPv6(data)) { - if (!PacketUtils.isTCPForIpv6(data)) { return next(); } + if (!PacketUtils.isTCPForIpv6(data)) { + return next(); + } } else { return next(); } @@ -375,10 +427,10 @@ export default function(data: Buffer, write: (data: Buffer) => void, next: () => }, write); session.once("closed", () => { delete connections[tcpConnectionId]; - // console.log("bye bye", PacketUtils.ipAddressToString(tcpPacket.destinationIp), "source port", session.connection.targetPort); + // if(TCP_LOG_ENABLE)console.log("bye bye", PacketUtils.ipAddressToString(tcpPacket.destinationIp), "source port", session.connection.targetPort); }); connections.set(tcpConnectionId, session); - // console.log("connect", PacketUtils.ipAddressToString(tcpPacket.destinationIp), "source port", tcpPacket.sourcePort); + // if(TCP_LOG_ENABLE)console.log("connect", PacketUtils.ipAddressToString(tcpPacket.destinationIp), "source port", tcpPacket.sourcePort); } session.dataRouter(data, tcpPacket); } diff --git a/test/shadowsocks/ShadowsocksFormatter.ts b/test/shadowsocks/ShadowsocksFormatter.ts index 5492757..4dbdf82 100644 --- a/test/shadowsocks/ShadowsocksFormatter.ts +++ b/test/shadowsocks/ShadowsocksFormatter.ts @@ -85,7 +85,7 @@ export default class ShadowsocksFormatter { } for (let i = 0; i < ipBuffer.length; i++) { - buffer[i + (header.version === ShadowsocksHeaderVersion.Domain ? 2 : 1)] = ipBuffer[i]; + buffer[i + 1] = ipBuffer[i]; } buffer[buffer.length - 2] = ((header.port >> 8) & 0xff); buffer[buffer.length - 1] = (header.port & 0xff); diff --git a/test/shadowsocks/ShadowsocksPing.ts b/test/shadowsocks/ShadowsocksPing.ts new file mode 100644 index 0000000..b3fb996 --- /dev/null +++ b/test/shadowsocks/ShadowsocksPing.ts @@ -0,0 +1,48 @@ +import {Address} from 'cluster'; +import {ShadowsocksHeaderVersion} from './ShadowsocksFormatter'; +import ShadowsocksTcpClient from './ShadowsocksTcpClient'; +import TcpPing, {PingResult,IPing,PingOptions} from './../util/TcpPing'; +import { IpcNetConnectOpts } from 'net'; + +export interface ShadowsocksPingOptions extends PingOptions{ + method :string, + passwd :string, + attempts:number +} + +export interface ShadowsocksPingResult extends PingResult{ + available:boolean +} + +export default class ShadowsocksPing implements IPing{ + + public async ping(options:ShadowsocksPingOptions) { + const targetAddress : Buffer = Buffer.from("google.com"); + const targetPort : number = 80; + let shadowsocksTcpClient :ShadowsocksTcpClient; + let result:ShadowsocksPingResult; + return new Promise(async (reslove,reject)=>{ + result = await new TcpPing().ping(options) as ShadowsocksPingResult + if (result.min === undefined) { + reject(new Error(`shadowsocks ${options.address}:${options.port} server unavailable!`)) + return; + } + // verify shadowsocks config is vaild + shadowsocksTcpClient = new ShadowsocksTcpClient(options.address, options.port,options.passwd ,options.method, ShadowsocksHeaderVersion.Domain, targetAddress, targetPort) + shadowsocksTcpClient.once("connected", () => { + shadowsocksTcpClient.write(Buffer.from("GET / HTTP/1.1\r\n\r\n")); + }) + shadowsocksTcpClient.once("data", (data) => { + result.available = true; + reslove(result); + }) + shadowsocksTcpClient.connect(ShadowsocksHeaderVersion.Domain, targetAddress, targetPort); + setTimeout(() => { + shadowsocksTcpClient.destroy(); + reject(new Error(`shadowsocks ${options.address}:${options.port} server unavailable!`)) + }, options.timeout); + }) + + + } +} \ No newline at end of file diff --git a/test/shadowsocks/ShadowsocksTcpClient.ts b/test/shadowsocks/ShadowsocksTcpClient.ts index b3ae758..e93941e 100644 --- a/test/shadowsocks/ShadowsocksTcpClient.ts +++ b/test/shadowsocks/ShadowsocksTcpClient.ts @@ -2,10 +2,21 @@ import * as net from "net"; import * as EventEmitter from "events"; import SSCrypto from "./crypto/SSCrypto"; -import ShadowsocksFormatter, { ShadowsocksHeaderVersion } from "./ShadowsocksFormatter"; +import ShadowsocksFormatter, {ShadowsocksHeaderVersion} from "./ShadowsocksFormatter"; +import {Address} from "cluster"; + + +export interface ShadowsocksOptions{ + host :string, + port :string, + method :string, + passwd :string, +} + export default class ShadowsocksTcpClient extends EventEmitter { + private method: any; private readonly socket: net.Socket = new net.Socket(); @@ -13,30 +24,33 @@ export default class ShadowsocksTcpClient extends EventEmitter { private buffersCache: Array = []; private isConnected: boolean = false; - constructor( - private host: string, - private port: number, - password: string, method: string, - private isIpv4Address: boolean = true, - private targetHost: Buffer = Buffer.allocUnsafe(0), - private targetPort: number = 0, - ) { + constructor(private host: string, + private port: number, + password: string, method: string, + private addressType: ShadowsocksHeaderVersion = ShadowsocksHeaderVersion.IPv4, + private targetHost: Buffer = Buffer.allocUnsafe(0), + private targetPort: number = 0) { super(); this.method = SSCrypto.createCryptoMethodObject(method, password); this.socket.setNoDelay(true); } - public connect(isIpv4Address: boolean, targetHost?: Buffer, targetPort?: number) { + public connect(addressType: ShadowsocksHeaderVersion, targetHost?: Buffer, targetPort?: number) { + this.socket.on("data", this.onData.bind(this)); this.socket.on("error", this.disconnect.bind(this)); this.socket.connect(this.port, this.host, this.onConnected.bind(this)); + if (ShadowsocksHeaderVersion) { + this.addressType = addressType; + } if (targetHost) { + // if addressType is domain,the first byte is the domain length this.targetHost = targetHost; } if (targetPort) { this.targetPort = targetPort; } - this.isIpv4Address = isIpv4Address; + } public disconnect() { @@ -60,7 +74,7 @@ export default class ShadowsocksTcpClient extends EventEmitter { /* support ipv4, ipv6 without domain */ private onConnected() { const headerBuffer: Buffer = ShadowsocksFormatter.build({ - version: this.isIpv4Address ? ShadowsocksHeaderVersion.IPv4 : ShadowsocksHeaderVersion.IPv6, + version: this.addressType, address: this.targetHost, port: this.targetPort, }); diff --git a/test/test.ts b/test/test.ts index 0064f30..54a544d 100644 --- a/test/test.ts +++ b/test/test.ts @@ -12,11 +12,12 @@ import PacketUtils from "./PacketUtils"; import * as cprocess from "child_process"; import * as NativeTypes from "./NativeTypes"; import DeviceConfiguration from "./DeviceConfiguration"; +import ShadowsocksPing, {ShadowsocksPingResult} from "./shadowsocks/ShadowsocksPing"; // tslint:disable-next-line:no-var-requires const optimist = require("optimist") .usage("Usage: $0 --host [shadowsocks host] --port [shadowsocks port] --passwd [shadowsocks password] --xtudp [x times udp packets]") - .default("xtudp", 1) + .default("xtudp", 0) .default("host", undefined) .default("port", undefined) .default("passwd", undefined) @@ -125,6 +126,22 @@ async function main() { process.exit(-1); } + /* verify shadowsocks server is available */ + try { + const pingResult: ShadowsocksPingResult = await new ShadowsocksPing().ping({ + address: Config.get("ShadowsocksTcpHost"), + port: Config.get("ShadowsocksTcpPort"), + passwd: Config.get("ShadowsocksTcpPasswd"), + method: Config.get("ShadowsocksTcpMethod"), + attempts: 10, + }); + console.log(`shadowsocks server:${pingResult.address} ping delay max: ${pingResult.max}ms,avg:${pingResult.avg},min:${pingResult.min}`) + }catch(error){ + console.log(error) + return; + } + + /* 设置OpenVPN网卡 */ if (!TAPControl.checkAdapterIsInstalled()) { console.log("Installing driver..."); @@ -145,9 +162,15 @@ async function main() { /* 获取默认网卡 */ const allDevicesInfo: Array = native.N_GetAllDevicesInfo() as Array; const defaultGateway: string = (native.N_GetIpforwardEntry() as Array)[0].nextHop; + // console.log(`${JSON.stringify(native.N_GetIpforwardEntry())}`) + // console.log(`默认网卡:${defaultGateway}`); + // console.log(`${JSON.stringify(allDevicesInfo)}`) let defaultDevice: NativeTypes.DeviceInfo = null; for (const device of allDevicesInfo) { - if (device.gatewayIpAddress === defaultGateway) { + // if (device.gatewayIpAddress === defaultGateway) { + // defaultDevice = device; + // } + if (device.index === tapInfo.index) { defaultDevice = device; } } @@ -183,14 +206,13 @@ async function main() { /* 设置路由表 */ { const initCommands: Array> = [ + ["route", "delete", "0.0.0.0", DeviceConfiguration.GATEWAY_IP_ADDRESS], + ["route", "delete", Config.get("DNS")], ["netsh", "interface", "ipv4", "set", "interface", `${tapInfo.index}`, "metric=1"], ["netsh", "interface", "ipv6", "set", "interface", `${tapInfo.index}`, "metric=1"], ["netsh", "interface", "ipv4", "set", "dnsservers", `${tapInfo.index}`, "static", Config.get("DNS"), "primary"], ["netsh", "interface", "ip", "set", "address", `name=${tapInfo.index}`, "static", DeviceConfiguration.LOCAL_IP_ADDRESS, DeviceConfiguration.LOCAL_NETMASK, DeviceConfiguration.GATEWAY_IP_ADDRESS], - ["route", "delete", "0.0.0.0", DeviceConfiguration.GATEWAY_IP_ADDRESS], - ["route", "delete", Config.get("DNS")], - ["route", "add", Config.get("ShadowsocksTcpHost"), "mask", "255.255.255.255", defaultGateway, "metric", "1"], ["route", "add", Config.get("ShadowsocksUdpHost"), "mask", "255.255.255.255", defaultGateway, "metric", "1"], ]; @@ -199,7 +221,7 @@ async function main() { initCommands.push( ["route", "add", Config.get("DNS"), "mask", "255.255.255.255", defaultGateway, "metric", "1"], ["netsh", "interface", "ipv4", "set", "dnsservers", `${tapInfo.index}`, "static", DeviceConfiguration.GATEWAY_IP_ADDRESS, "primary"], - ["netsh.exe", "interface", "ipv6", "set", "dnsserver", `name=${tapInfo.index}`, "source=static", `address=""`, "validate=no"], + ["netsh", "interface", "ipv6", "set", "dnsserver", `name=${tapInfo.index}`, "source=static", `address=""`, "validate=no"], ); } @@ -213,7 +235,7 @@ async function main() { initCommands.push( ["netsh", "interface", "ipv6", "set", "address", `interface=${tapInfo.index}`, `address=${DeviceConfiguration.LOCAL_IPV6_ADDRESS}`], ["netsh", "interface", "ipv6", "add", "route", "::/0", `interface=${tapInfo.index}`, `nexthop=${DeviceConfiguration.GATEWAY_IPV6_ADDRESS}`], - ["netsh.exe", "interface", "ipv6", "set", "dnsserver", `name=${tapInfo.index}`, "source=static", `address=${argv.v6dns}`, "validate=no"], + ["netsh", "interface", "ipv6", "set", "dnsserver", `name=${tapInfo.index}`, "source=static", `address=${argv.v6dns}`, "validate=no"], ); } @@ -271,13 +293,15 @@ async function main() { // tslint:disable-next-line:ban-types const filters: Array = []; - filters.push(require("./filters/TCP").default); + filters.push(require("./tunnel/ShadowsocksTunnel").default); filters.push(require("./filters/DNS").default); filters.push(require("./filters/UDP").default); filters.push(require("./filters/ARP").default); filters.push(require("./filters/NDP").default); - filters.push(require("./filters/TimesUDP").default); - + if (Config.get("XTUdp") > 0) { + filters.push(require("./filters/TimesUDP").default); + } + console.log("start...") async function loop() { const data: Buffer = await tapControl.read() as Buffer; let index: number = 0; diff --git a/test/tunnel/ShadowsocksTunnel.ts b/test/tunnel/ShadowsocksTunnel.ts new file mode 100644 index 0000000..52724d2 --- /dev/null +++ b/test/tunnel/ShadowsocksTunnel.ts @@ -0,0 +1,71 @@ +import * as EventEmitter from "events"; +import {TcpServerSession, TcpStack} from "../filters/TCP" +import ShadowsocksTcpClient from './../shadowsocks/ShadowsocksTcpClient'; +import { ShadowsocksHeaderVersion } from "../shadowsocks/ShadowsocksFormatter"; +import { EthernetType } from "../PacketsStruct"; +import Config from "../Config"; + +const SHADOWSOCKS_TUNNEL_LOG_ENABLE = false; + +class ShadowsocksTunnel extends EventEmitter{ + private shadowsocksTcpClient : ShadowsocksTcpClient = null; + + constructor( + private host:string, + private port:number, + private passwd:string, + private method:string, + private tcpSession:TcpServerSession + ){ + super(); + if(SHADOWSOCKS_TUNNEL_LOG_ENABLE)console.log("start tunnel") + const ipversion:ShadowsocksHeaderVersion = tcpSession.connection.ipversion == EthernetType.IPv4 ? ShadowsocksHeaderVersion.IPv4:ShadowsocksHeaderVersion.IPv6; + this.shadowsocksTcpClient = new ShadowsocksTcpClient( + host, + port, + passwd, + method, + ipversion, + this.tcpSession.connection.localIp, + this.tcpSession.connection.localPort + ); + this.shadowsocksTcpClient.connect(ipversion,null,null); + this.shadowsocksTcpClient.on("data",this.shadowsocksToTcp.bind(this)); + this.shadowsocksTcpClient.on("disconnected",this.shadowsocksDisconnected.bind(this)); + this.tcpSession.on("read",this.tcpToShadowsocks.bind(this)); + } + + private shadowsocksToTcp(data:Buffer){ + if(SHADOWSOCKS_TUNNEL_LOG_ENABLE)console.log("send data to tcp") + this.shadowsocksTcpClient.pause(true); + this.tcpSession.write(data); + this.shadowsocksTcpClient.pause(false); + } + + private tcpToShadowsocks(data:Buffer){ + // console.log("send data to shadowsocks server") + this.shadowsocksTcpClient.write(data); + } + + private shadowsocksDisconnected(){ + if(SHADOWSOCKS_TUNNEL_LOG_ENABLE)console.log(`close ${this.tcpSession.connection.localIp}:${this.tcpSession.connection.localPort}`) + this.tcpSession.close(); + } + +} + +export default function (data: Buffer, write: (data: Buffer) => void, next: () => void) { + const tcpStack :TcpStack = new TcpStack(write); + tcpStack.on("accept",(session)=>{ + if(SHADOWSOCKS_TUNNEL_LOG_ENABLE)console.log("accept new session") + new ShadowsocksTunnel( + Config.get("ShadowsocksTcpHost"), + Config.get("ShadowsocksTcpPort"), + Config.get("ShadowsocksTcpPasswd"), + Config.get("ShadowsocksTcpMethod"), + session + ) + }) + tcpStack.input(data); + next(); +} diff --git a/test/util/TcpPing.ts b/test/util/TcpPing.ts new file mode 100644 index 0000000..5eada86 --- /dev/null +++ b/test/util/TcpPing.ts @@ -0,0 +1,96 @@ +import {Socket} from 'net' + +export interface PingOptions { + address : string, + port : number, + attempts?: number, + timeout?: number +} + +export interface PingResult { + address : string, + port : number, + attempts : number, + avg : number, + max : number, + min : number, + results : Array < PingResultItem > +} + +export interface PingResultItem { + seq : number, + time : number, + err?: any +} + +export interface IPing{ + ping(options:PingOptions):any +} +export default class TcpPing implements IPing { + public ping(options : PingOptions) : Promise < PingResult > { + return new Promise < PingResult > (function (reslove, reject) { + let i = 0; + let results : Array < PingResultItem >= []; + options.address = options.address || 'localhost'; + options.port = options.port || 80; + options.attempts = options.attempts || 10; + options.timeout = options.timeout || 5000; + let check = function (options) { + if (i < options.attempts) { + connect(options); + } else { + let avg = results.reduce(function (prev, curr) { + return prev + curr.time; + }, 0); + let max = results.reduce(function (prev, curr) { + return (prev > curr.time) + ? prev + : curr.time; + }, results[0].time); + let min = results.reduce(function (prev, curr) { + return (prev < curr.time) + ? prev + : curr.time; + }, results[0].time); + avg = avg / results.length; + let out : PingResult = { + address: options.address, + port: options.port, + attempts: options.attempts, + avg: avg, + max: max, + min: min, + results: results + }; + reslove(out); + } + }; + + let connect = function (options) { + let s = new Socket(); + let start = process.hrtime(); + s.connect(options.port, options.address, function () { + let time_arr = process.hrtime(start); + let time = (time_arr[0] * 1e9 + time_arr[1]) / 1e6; + results.push({seq: i, time: time}); + s.destroy(); + i++; + check(options); + }); + s.on('error', function (e) { + results.push({seq: i, time: undefined, err: e}); + s.destroy(); + i++; + check(options); + }); + s.setTimeout(options.timeout, function () { + results.push({seq: i, time: undefined, err: Error('Request timeout')}); + s.destroy(); + i++; + check(options); + }); + }; + connect(options); + }); + } +} \ No newline at end of file