> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Windows 11 Multi-User Remote Desktop (RDP) Setup

> Lift the single-session limit on Windows 11 Remote Desktop using RDP Wrapper for concurrent multi-user sessions: install and verify, NLA and session security, router port forwarding, Cloudflare access, and troubleshooting.

export const OptionPicker = ({options = [], lang = "zh", label}) => {
  const t = lang === "en" ? {
    pick: label || "Pick an option to compare",
    rec: "Recommended"
  } : {
    pick: label || "點選項目比較",
    rec: "推薦"
  };
  const opts = Array.isArray(options) ? options : [];
  const [sel, setSel] = useState(0);
  if (opts.length === 0) return null;
  const idx = Math.min(sel, opts.length - 1);
  const cur = opts[idx];
  const css = `
  .op-root{--op-bg:#FAF8F3;--op-surface:rgba(0,0,0,0.025);--op-border:rgba(0,0,0,0.09);--op-text:#2b2722;--op-dim:#6f6a62;--op-faint:#8a8378;--op-accent:#bf7551;border:1px solid var(--op-border);border-radius:14px;background:var(--op-bg);color:var(--op-text);overflow:hidden;}
  .dark .op-root{--op-bg:#1b1a18;--op-surface:rgba(255,255,255,0.03);--op-border:rgba(255,255,255,0.08);--op-text:#e7e3da;--op-dim:#a8a299;--op-faint:#8a8378;--op-accent:#cf8a68;}
  .op-head{padding:12px 16px 11px;border-bottom:1px solid var(--op-border);font-size:12.5px;color:var(--op-dim);display:flex;align-items:center;gap:8px;}
  .op-head-ic{color:var(--op-accent);flex-shrink:0;}
  .op-tabs{display:flex;gap:8px;padding:14px 16px 4px;flex-wrap:wrap;}
  .op-tab{position:relative;flex:1 1 130px;min-width:120px;text-align:left;background:transparent;border:1px solid var(--op-border);border-radius:11px;padding:11px 13px;cursor:pointer;color:inherit;font:inherit;transition:border-color .15s,background .15s,box-shadow .15s;}
  .op-tab:hover{background:var(--op-surface);}
  .op-tab-on{border-color:rgba(191,117,81,.5);background:rgba(191,117,81,.07);box-shadow:0 0 0 3px rgba(191,117,81,.1);}
  .op-tab-name{font-size:14.5px;font-weight:600;line-height:1.3;}
  .op-tab-on .op-tab-name{color:var(--op-accent);}
  .op-badge{display:inline-block;margin-top:6px;font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;padding:2px 7px;border-radius:20px;background:rgba(191,117,81,.14);color:var(--op-accent);}
  .op-rec{position:absolute;top:10px;right:11px;font-size:10px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;color:var(--op-accent);}
  .op-body{padding:6px 16px 16px;}
  .op-specs{border:1px solid var(--op-border);border-radius:10px;overflow:hidden;margin-bottom:11px;}
  .op-row{display:flex;border-top:1px solid var(--op-border);font-size:13px;}
  .op-row:first-child{border-top:none;}
  .op-k{width:42%;flex-shrink:0;padding:8px 12px;color:var(--op-dim);background:var(--op-surface);}
  .op-v{flex:1 1 0;min-width:0;padding:8px 12px;font-weight:500;}
  .op-note{font-size:13px;line-height:1.6;color:var(--op-dim);padding:0 2px;}
  `;
  return <div className="op-root">
      <style>{css}</style>
      <div className="op-head"><svg className="op-head-ic" xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z" /><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65" /><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65" /></svg>{t.pick}</div>
      <div className="op-tabs">
        {opts.map((o, i) => <button key={i} type="button" className={"op-tab" + (i === idx ? " op-tab-on" : "")} onClick={() => setSel(i)}>
            {o.recommend && <span className="op-rec">★ {t.rec}</span>}
            <div className="op-tab-name">{o.name}</div>
            {o.badge && <span className="op-badge">{o.badge}</span>}
          </button>)}
      </div>
      <div className="op-body">
        <div className="op-specs">
          {(cur.specs || []).map((row, i) => <div className="op-row" key={i}>
              <div className="op-k">{row[0]}</div>
              <div className="op-v">{row[1]}</div>
            </div>)}
        </div>
        {cur.note && <div className="op-note">{cur.note}</div>}
      </div>
    </div>;
};

`Windows 11` `RDP` `RDP Wrapper` `Cloudflare`

Windows 11 Remote Desktop allows only one concurrent session by default. RDP Wrapper Library lets multiple users hold independent sessions without buying a Windows Server license.

<Warning>
  The RDP concurrent-session limit is part of Microsoft's licensing terms. Methods that lift it **may violate those terms**. Assess the risk yourself, confirm it fits your organization's policy, and for enterprise or business-critical use prefer a licensed Windows Server RDS deployment. All IPs, ports, and domains below are placeholders: replace them, and never publish your real external address, port mappings, or accounts.
</Warning>

## Two methods

<OptionPicker
  lang="en"
  options={[
{
  name: "RDP Wrapper Library",
  badge: "Recommended",
  recommend: true,
  specs: [
    ["Mechanism", "Wraps the RDP service, leaves termsrv.dll intact"],
    ["Stability", "Better; safe to run Windows updates"],
    ["Complexity", "Medium"],
    ["Maintenance", "Occasional rdpwrap.ini update"],
  ],
  note: "Does not touch core system files; relatively safe. Primary method here.",
},
{
  name: "Patch termsrv.dll",
  specs: [
    ["Mechanism", "Patches the system file directly"],
    ["Stability", "Fair; updates may overwrite the patch"],
    ["Complexity", "Simple"],
    ["Maintenance", "Re-apply after Windows updates"],
  ],
  note: "Patching a core system file is riskier; only consider it with infrequent updates.",
},
]}
/>

## Requirements

* Windows 11 Pro or Enterprise, administrator rights
* 8GB+ RAM recommended; enough resources for concurrent sessions
* Open the RDP port (default TCP `3389`, can be changed to non-standard)

## Method 1: RDP Wrapper setup

<Steps>
  <Step title="Download RDP Wrapper">
    Get the latest `.zip` from [RDP Wrapper releases](https://github.com/stascorp/rdpwrap/releases) and extract it somewhere accessible (e.g. `D:\RDPWrapper`).
  </Step>

  <Step title="Verify the extracted files">
    Should include `RDPWinst.exe`, `RDPConf.exe`, `RDPCheck.exe`, `install.bat`, `uninstall.bat`, `update.bat`.
  </Step>

  <Step title="Install as administrator">
    Right-click `install.bat` → "Run as administrator". If access is denied, temporarily disable Windows Defender protection and retry. It installs to `C:\Program Files\RDP Wrapper`.
  </Step>

  <Step title="Verify the install">
    Run `RDPConf.exe` and check Diagnostics: green is fine, red (`not supported`) means the config needs updating.
  </Step>

  <Step title="Update rdpwrap.ini (if red warnings)">
    Open `C:\Program Files\RDP Wrapper\rdpwrap.ini` as administrator and replace its contents entirely with the community-maintained config:

    ```text theme={null}
    https://raw.githubusercontent.com/sebaxakerhtc/rdpwrap.ini/master/rdpwrap.ini
    ```

    Save, restart, then run `RDPConf.exe` again to confirm all green.
  </Step>

  <Step title="Test multi-user connection">
    Run `RDPCheck.exe` for a local test, create multiple user accounts, and connect concurrently from different devices.
  </Step>
</Steps>

### Key RDP service settings

<Tabs>
  <Tab title="General">
    | Setting               | Function               | Security note                              |
    | --------------------- | ---------------------- | ------------------------------------------ |
    | Enable Remote Desktop | Starts the RDP service | Pair with firewall source limits           |
    | RDP port              | TCP port to listen on  | Non-standard port lowers automated attacks |
    | Hide users on logon   | Hides the account list | Avoids leaking account info                |
  </Tab>

  <Tab title="Authentication">
    | Mode                             | Security | Notes                                                                 |
    | -------------------------------- | -------- | --------------------------------------------------------------------- |
    | GUI Authentication Only          | Low      | GUI login only after a full session is built                          |
    | Default RDP Authentication       | Medium   | Standard RDP encrypted auth                                           |
    | **Network Level Authentication** | **High** | Recommended; authenticates before the session, mitigates DoS and MITM |
  </Tab>

  <Tab title="Shadowing">
    | Mode                           | Privacy | Notes                                 |
    | ------------------------------ | ------- | ------------------------------------- |
    | Disable Shadowing              | Highest | Session monitoring off                |
    | View only with permission      | High    | View only after consent               |
    | Full access with permission    | Medium  | Full control after consent            |
    | Full access without permission | None    | Takes over without consent; intrusive |
  </Tab>
</Tabs>

## External access

To connect from outside, set up router port forwarding, ideally behind Cloudflare.

<Steps>
  <Step title="Find the internal IP and make it static">
    Run `ipconfig` on the target PC, note the IPv4 (e.g. `192.168.x.x`), and set a static IP or DHCP reservation so forwarding does not break on address changes.
  </Step>

  <Step title="Router port forwarding">
    Add a rule under the router's Port Forwarding / Virtual Server:

    | Setting       | Example           | Notes                     |
    | ------------- | ----------------- | ------------------------- |
    | Internal IP   | `192.168.x.x`     | Target PC LAN IP          |
    | External port | `<external-port>` | Custom non-standard port  |
    | Internal port | `3389`            | Match the RDPConf setting |
    | Protocol      | TCP               |                           |

    <Tip>Use a non-standard external port (not 3389) to reduce port-scan and automated-attack exposure.</Tip>
  </Step>

  <Step title="Allow through Windows Firewall">
    `win + R` → `wf.msc`, add an inbound rule: type "Port", protocol TCP, your RDP port, action "Allow the connection".
  </Step>

  <Step title="Test connectivity">
    Internally: `telnet 192.168.x.x 3389`. Externally: from a phone hotspot, `telnet <public-ip> <external-port>` or an online open-port checker.
  </Step>

  <Step title="Cloudflare (pick one)">
    * **A record (quick)**: add an A record in Cloudflare DNS pointing at your public IP, Proxy set to "DNS only (grey cloud)".
    * **Cloudflare Tunnel (recommended)**: no open router port, automatic TLS, DDoS protection. Install [cloudflared](https://github.com/cloudflare/cloudflared/releases), then:

    ```yaml theme={null}
    # config.yml
    tunnel: <tunnel-id>
    credentials-file: <path-to-credentials>
    ingress:
      - hostname: remote.your-domain.com
        service: rdp://localhost:3389
      - service: http_status:404
    ```
  </Step>
</Steps>

## Client connection

<Tabs>
  <Tab title="PC">
    * Built-in Remote Desktop Connection (`mstsc`): enter `address:port`, log in with credentials.
    * Microsoft Remote Desktop app: add a PC with the address and credentials.
    * Command line: `mstsc /v:<host>:<port>`.
  </Tab>

  <Tab title="Mobile">
    Install **Microsoft Remote Desktop** (Windows App) on iOS / Android, add the remote PC with the external address, port, and credentials. Lower the image quality on mobile networks for smoother sessions.
  </Tab>
</Tabs>

## Troubleshooting

| Symptom                      | Likely cause                                 | Where to look                                                                                   |
| ---------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| RDPConfig shows red          | `rdpwrap.ini` stale or termsrv.dll modified  | Update the ini, `sfc /scannow`, reinstall RDP Wrapper                                           |
| No connection after patching | Service not restarted, firewall, permissions | Restart `TermService`/`UmRdpService`, check firewall, confirm account in "Remote Desktop Users" |
| Breaks after Windows update  | System file restored or config overwritten   | Recheck RDPConf, update the ini, restart                                                        |
| Slow with many sessions      | Resource/bandwidth limits                    | Add RAM, lower color depth, use wired networking                                                |

<Warning>
  Before running GPU training on a shared multi-user host, confirm no one else is using the GPU to avoid `OOM`.
</Warning>

## Hardening

* Enable **NLA** (Network Level Authentication) to authenticate before the session.
* Move RDP off the default port and set a source-IP allowlist in the firewall.
* Account lockout policy (e.g. 5 failures → 30 min) and audit both successful and failed logons.
* Grant "Allow log on through Remote Desktop Services" only to needed users; explicitly deny high-risk accounts.
* Strong password policy plus 2FA; review `TerminalServices-LocalSessionManager` event logs regularly.

## Links

<Note>
  This page is a public, sanitized version of the private organization repo [issp-mes-lab/remote-win11-pc](https://github.com/issp-mes-lab/remote-win11-pc), with lab-internal addresses, ports, and accounts removed. The source repo is private and requires organization access.
</Note>

* Source repo (private): [issp-mes-lab/remote-win11-pc](https://github.com/issp-mes-lab/remote-win11-pc)
* [RDP Wrapper Library](https://github.com/stascorp/rdpwrap) (core multi-session tool)
* [Community-maintained rdpwrap.ini](https://github.com/sebaxakerhtc/rdpwrap.ini)
* [Cloudflare Tunnel (cloudflared)](https://github.com/cloudflare/cloudflared/releases)
