VBScript修改Windows远程协助桌面连接默认3389端口
提醒:本页面将不再更新、维护或者支持,文章、评论所叙述内容存在时效性,涉及技术细节或者软件使用方面不保证能够完全有效可操作,请谨慎参考!
最近在配置一台Windows Server 2008 R2的服务器,本来想装上个VNC的,不过想想Windows自带有远程桌面,就没必要这么麻烦了,于是开启了远程桌面访问,并且在TMG防火墙规则中配置了RDP(Terminal Services) Server规则,一切都很顺利,当路由器上映射完3389端口后,客户端成功访问并且连接!
可是过了一段时间发现,远程连接被断开,局域网连接仍然可以,外网死活都连接不上,于是查阅了TMG防火墙日志,发现有段大量不同IP尝试连接3389的记录,并且被TMG侦测为FLOOD攻击,所以拒绝了所有的外网请求,看来不能用默认的3389端口了,所以要更改默认的远程端口,具体怎么改,其实在Windows XP时代我就尝试着找可以改动的图形化界面,可是一直找不到最后还是修改注册表才更改成功。貌似现在在Win2008时代依旧不能找到图形化修改界面,看来又要修改注册表了。主要修改以下两条注册表信息的PortNamber值:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp\
为了避免以后再遇到这类问题,我觉得有必要写个脚本来解决。我们知道在VBScript中修改注册表有两种方式,第一种是使用组件WScript.Shell的RegWrite方法,遗憾的是这种方式常常会使杀毒软件误认为是病毒,因为有段时间WScript.Shell在网页挂马技术上很是流行,导致现在很多安全软件都封杀或者重点监控这个ActvieX组件。第二种是使用WMI方式,这个是我比较推荐的,下面的脚本将说明这些问题。
在提供脚本之前,大家可以到微软的 脚本中心 参考一下WMI操作注册表的一些方法。
' Author : WangYe
' For more information please visit http://wangye.org/
Option Explicit
Const AppTitle = "Modify RDP Port Number"
Const StatusOk = 0
Const StatusInvalidPortNumber = -1
Const StatusSetRDPPortNumberFailed = -2
Const StatusSetTDSPortNumberFailed = -3
Const L_Invalid_PortNumber_Text = "ERROR : Invalid port number."
Const L_User_Cancelled_Text = "User cancelled."
Const HKEY_LOCAL_MACHINE = &H80000002
Const RDPTcpPath =_
"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\"
Const TDSTcpPath =_
"SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp\"
Class RDPTS
Private strComputer
Private Registry
Private Sub Class_Initialize()
strComputer = "."
Set Registry = GetObject(_
"winmgmts:{impersonationLevel=impersonate}!\\" &_
strComputer & "\root\default:StdRegProv")
End Sub
Private Sub Class_Terminate()
Set Registry = Nothing
End Sub
Function isPortAlreadyExists(portnum)
' 判断端口是否冲突(尚未实现)
isPortAlreadyExists = False
End Function
Public Function getPortNumber(lowerbound, upperbound)
If lowerbound < 4 Then lowerbound = 4
If upperbound > 65534 Then upperbound = 65535
Do
Randomize
getPortNumber = Int(_
(upperbound - lowerbound + 1)_
* Rnd + lowerbound)
Loop Until getPortNumber<>3389_
And (Not isPortAlreadyExists(getPortNumber))
End Function
Public Function isPortValid(portnum)
isPortValid = False
If Not IsNumeric(portnum) Then
Exit Function
End If
If portnum < 4 Then
Exit Function
End If
If portnum > 65534 Then
Exit Function
End If
isPortValid = True
End Function
Public Function getRDPTcpPortNumber()
Registry.GetDWORDValue HKEY_LOCAL_MACHINE,_
RDPTcpPath,"PortNumber",getRDPTcpPortNumber
End Function
Public Function getTDSTcpPortNumber()
Registry.GetDWORDValue HKEY_LOCAL_MACHINE,_
TDSTcpPath,"PortNumber",getTDSTcpPortNumber
End Function
Public Function setRDPTcpPortNumber(portnum)
On Error Resume Next
setRDPTcpPortNumber = True
Registry.SetDWORDValue HKEY_LOCAL_MACHINE,_
RDPTcpPath,"PortNumber",portnum
If Err Then Err.Clear : setRDPTcpPortNumber = False
End Function
Public Function setTDSTcpPortNumber(portnum)
On Error Resume Next
setTDSTcpPortNumber = True
Registry.SetDWORDValue HKEY_LOCAL_MACHINE,_
TDSTcpPath,"PortNumber",portnum
If Err Then Err.Clear : setTDSTcpPortNumber = False
End Function
Public Function addFirewallPolicy(portnum, name, state)
Dim netfw, policy, port, ports
Set netfw = WScript.CreateObject("HNetCfg.FwMgr")
Set policy = netfw.LocalPolicy.CurrentProfile
Set port = WScript.CreateObject("HNetCfg.FwOpenPort")
port.Port = portnum
port.Name = name
port.Enabled = state
Set ports = policy.GloballyOpenPorts
addFirewallPolicy = ports.Add(port)
Set ports = Nothing
Set port = Nothing
Set policy = Nothing
Set netfw = Nothing
End Function
End Class
Function VBMain()
VBMain = StatusOk
Dim RDS, portnum, source
Set RDS = New RDPTS
portnum = RDS.getPortNumber(3390, 65530)
source = InputBox("Original port number detected:" & vbCrLf &_
"RDP-TCP(" & RDS.getRDPTcpPortNumber() &_
"), TDS-TCP(" & RDS.getTDSTcpPortNumber() &_
")" & vbCrLf & vbCrLf &_
"Please Enter the new port number" & vbCrLf &_
"for RDP(Terminal Services) Server", _
AppTitle, portnum)
If source = "" Then
WScript.Echo L_User_Cancelled_Text
Exit Function
End If
If Not RDS.isPortValid(source) Then
WScript.Echo L_Invalid_PortNumber_Text
VBMain = StatusInvalidPortNumber
Exit Function
End If
portnum = source
If MsgBox("Pending changes : " & vbCrLf & vbCrLf &_
"RDP-TCP ` " & RDS.getRDPTcpPortNumber() &_
" -> " & portnum & " `" & vbCrLf &_
"TDS-TCP ` " & RDS.getTDSTcpPortNumber() &_
" -> " & portnum & " `" & vbCrLf & vbCrLf &_
"Are you sure?", vbOKCancel, AppTitle) = vbCancel Then
WSH.Echo "Cancelled, No changes occured."
Exit Function
End If
If Not RDS.setRDPTcpPortNumber(portnum) Then
WSH.Echo "Set RDP-TCP port number `" &_
RDS.getRDPTcpPortNumber() & "` to `" &_
portnum & "` failed!"
VBMain = StatusSetRDPPortNumberFailed
Exit Function
End If
If Not RDS.setTDSTcpPortNumber(portnum) Then
WSH.Echo "Set TDS-TCP port number `" &_
RDS.getTDSTcpPortNumber() & "` to `" &_
portnum & "` failed!"
VBMain = StatusSetTDSPortNumberFailed
Exit Function
End If
If MsgBox("Do you want add port `" & portnum &_
"` to Windows Firewall policy?", vbOKCancel, AppTitle) = vbOK Then
Do
source = InputBox("Enter the name for this new policy",_
AppTitle, "RDP(Terminal Services)")
If source="" Then
If MsgBox("Policy name required, Do you want quit Add Policy?",_
vbOKCancel, AppTitle) = VbOK Then
Exit Do
End If
End If
Loop Until source<>""
If source<>"" Then
RDS.addFirewallPolicy portnum, source, 1
End If
End If
WScript.Echo "All done successfully!"
Set RDS = Nothing
End Function
Call WScript.Quit(VBMain())
好了,上面就是全部脚本,为了兼容不带中文的外文操作系统,我这里一些提示信息使用的是英语,很简单的词汇,想必大家应该能看懂的吧。isPortAlreadyExists这个函数尚未完成,是判断端口是否被其他程序占用的,实在找不到好的办法判断,这里先空着吧。对了,我们修改完端口,可能有必要将新端口加入到Windows防火墙规则中,当然如果你关闭了Windows防火墙,这一步就可以省略,不过你可能要修改其他现有防火墙的访问规则了。不能像我一样,有一次就是远程装完ISA防火墙,结果把自己关在外面了,安装前没有配置好规则惹的祸啊。
最后,打包好的脚本( RDP-ChangePorts.zip ):-)