VBScript修改Windows远程协助桌面连接默认3389端口

!本文可能 超过1年没有更新,今后内容也许不会被维护或者支持,部分内容可能具有时效性,涉及技术细节或者软件使用方面,本人不保证相应的兼容和可操作性。

最近在配置一台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操作注册表的一些方法。

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
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
' 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):-)

若无特别说明,本网站文章均为原创,原则上这些文章不允许转载,但是如果阁下是出于研究学习目的可以转载到阁下的个人博客或者主页,转载遵循创作共同性“署名-非商业性使用-相同方式共享”原则,请转载时注明作者出处谢绝商业性、非署名、采集站、垃圾站或者纯粹为了流量的转载。谢谢合作!
请稍后...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*