65.9K
CodeProject 正在变化。 阅读更多。
Home

托管 C++ 中的终端服务器监听端口实用程序

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.86/5 (7投票s)

2004年12月20日

CPOL

3分钟阅读

viewsIcon

69264

downloadIcon

1605

一个允许方便地将终端服务器的侦听端口从 3389 修改为其他端口的实用程序。

ts_port_utility/ts_port_utility.gif

插图 1:终端服务侦听端口实用程序 GUI

引言

终端服务和远程桌面都使用 RDP 协议,默认端口为 3389。Windows XP 中包含的远程桌面是终端服务的精简版本,因此它一次只允许一个用户会话。相比之下,Windows Server 2000 和 Windows Server 2003 中提供的终端服务可以用于两种不同的模式:

  • 远程管理 - 允许最多两个管理员用户登录;
  • 应用程序服务器模式 - 允许 n 个用户在服务器上处理应用程序。

Microsoft 作为 MMC 管理单元提供的终端服务配置和管理实用程序不提供任何 TCP 侦听端口选项。更改终端服务器默认端口 3389 的唯一方法是通过 Windows 注册表。

终端服务侦听端口实用程序旨在展示一个简单的托管 C++ 应用程序,该应用程序允许在支持的平台上方便地修改终端服务器的侦听端口。

支持的平台

  • Windows 2000 Server
  • Windows 2000 Advanced Server
  • Windows XP 专业版
  • Windows Server 2003

    [Windows XP Home 仅附带 RDP 客户端,不支持。]

背景

在我管理的多个实时终端服务器中,我开始寻找一种方法来使它们在网络上不那么显眼。将默认终端服务器端口从 3389 更改为其他端口似乎是一个不错的起点。实际上,这可以隐藏终端服务器,至少在理论上应该可以提高安全性。当然,终端服务器仍然可以在网络上被发现,但这只有在有人手动探测每个端口以获取 TS 响应的情况下才可能。

代码大纲

终端服务侦听端口实用程序从注册表中检索默认网络接口的终端服务器 TCP 端口值。用户可以指定一个新的端口值,如果新值代表一个有效端口,那么用户可以将这个新值存储到 Windows 注册表中。

注册表操作

通过 Microsoft::Win32::RegistryKey 类执行注册表访问,该类代表 Windows 注册表中的一个键级节点。此类是注册表封装,使用起来非常简单。

// Obtain Terminal Services Port from registry
private: System::Void MainForm_Load(System::Object * sender, 
                                      System::EventArgs * e)
{
    // Highest port possible is 65534 which is 5 characters
    txtPortNumber->MaxLength = 5;

    regKey = Registry->LocalMachine->
        OpenSubKey("System\\CurrentControlSet\\Control" 
                   "\\Terminal Server\\WinStations\\RDP-Tcp", 
        true );

    if(regKey != 0)    
        txtPortNumber->Text = 
           regKey->GetValue("PortNumber")->ToString();
    else
    {
        MessageBox::Show("Terminal Server not found in Registry");
        btnSet->Enabled = false;
    }
}

// Write New Port to Registry
private: System::Void btnSet_Click(System::Object * sender, 
                                     System::EventArgs * e)
{
    if(!IsValidPort(txtPortNumber->Text))
        errorProvider->SetError(txtPortNumber, 
             "A Port must be >= 1 and <= 65534");
    else
    {
        errorProvider->SetError(txtPortNumber, "");

        if(regKey != 0)
        {
            // store as REG_DWORD
            regKey->SetValue("PortNumber", 
              __box(Convert::ToInt32(txtPortNumber->Text))); 
            MessageBox::Show(String::Format("Port saved as {0}", 
              txtPortNumber->Text), "Success", 
              MessageBoxButtons::OK, MessageBoxIcon::Information);
        }
    }
}

验证例程

终端服务侦听端口实用程序实现了以下两个验证算法来限制输入并减少用户错误。

// determine whether the string qualifies as a port, 
// a valid port is an integer in the range of 1-65534 
private : bool IsValidPort(System::String * txtPort) 
{ 
    // we already know txtPort is numeric 
    // bit slow I suppose
    Int32 iPort = Int32::Parse(txtPort); 
    if (iPort < 1 || iPort > 65534) 
        return false; 
    else 
        return true; 
}
 
// determine whether the keystroke is an integer of the range 0-9 
// used in relation with the KeyPress event and Handled Property 
private : bool IsValidInt(System::String * ch) 
{ 
    String * format = "0123456789"; 

    if(format->IndexOf(ch)>=0) 
        return true; 
    else
        return false; 
} 

private: System::Void txtPortNumber_KeyPress(System::Object *  sender,
    System::Windows::Forms::KeyPressEventArgs *  e)
{
    // Stops the character from being entered
    // into the control since it is non-integer.
    if(!IsValidInt(e->KeyChar.ToString()) )
        e->Handled = true;
}

客户端配置

不要忘记将终端服务客户端或远程桌面客户端配置为连接到新端口,而不是默认端口 3389。防火墙或其他 NAT 相关设备可能需要重新配置,以便为任何新端口启用直通或端口转发。

例如,要指示远程桌面客户端实用程序使用新端口连接,只需在计算机地址字段中附加一个冒号,后跟非标准端口号。

插图 2:使用非标准端口的 XP 远程桌面客户端

相关资源

历史

  • 04/12/17:原始提交
  • 04/12/20:更新了资源
© . All rights reserved.