I tried Amazon WorkSpaces Personal because it supported PrivateLink for streaming
I'm Shibata.
About two months ago, Amazon WorkSpaces Personal added support for PrivateLink for streaming.
Here are the announcement and blog post from AWS:
Updates and Limitations
This PrivateLink enables WorkSpaces usage (streaming) through VPC Endpoints created within a VPC.
Similar to PrivateLink for other services, it would be adopted when there are constraints on communication paths, but there are quite a number of limitations that make adoption somewhat challenging.
Limitation 1: Environment Restrictions
First, as of today, this PrivateLink can only be used with Amazon WorkSpaces Personal.
Amazon WorkSpaces Pools is not supported.
Limitation 2: Communication Restrictions
Additionally, this PrivateLink can only be used with WorkSpace environments using the Amazon DCV protocol (formerly WSP protocol).
For PCoIP environments, you must choose either "Allow communication over the internet" or "No communication allowed" in the WorkSpaces directory settings.
Also, note that only streaming traffic goes through PrivateLink, while authentication traffic still requires internet access.
This specification is the same as Amazon AppStream 2.0, which has supported PrivateLink since 2019.
Please note that you cannot use Amazon WorkSpaces in a completely closed network environment.
Authentication traffic requires allowing TCP port 443 and UDP port 443 to specified domains.
Limitation 3: Feature Restrictions
Other functional limitations are listed in the following document:
In addition to the limitations mentioned above:
- Communication using VPC Endpoints in Amazon DCV protocol environments is mutually exclusive (with internet-based communication)
- When using VPC Endpoints, internet-based communication is blocked
- Currently only IPv4 is supported
- Routing must be possible from client environments to the VPC Endpoint
- FIPS encryption is not supported
- AWS Global Accelerator (AGA) cannot be used
- When configuring VPC Endpoints, IP access control group settings are disabled[1]
Testing It Out
From here, I'll actually try out the PrivateLink.### 0. Verification Environment
This time, we will create two VPCs in the Tokyo region of our verification AWS account: a source VPC (VPC1) and a VPC for Amazon WorkSpaces Personal (VPC2).
We will prepare one Japanese version Windows Server 2025 EC2 in the source VPC and install the latest Amazon WorkSpaces Client application on it.
Internet access will be configured through a NAT Instance, and by starting/stopping this NAT Instance, we can control internet access permission.
The Amazon WorkSpaces Personal environment will be created from the CloudFormation template previously published.
We will omit the procedures for building various resources.
1. Preparation (Security Groups)
First, we will create a security group for VPC Endpoints.
The security group rules need to allow the following communications:
- Inbound communications
- Allow TCP 443, 4195
- Allow UDP 443, 4195
- Outbound communications
- For VPC Endpoints, having no rules (blocking all communications) is OK
For the source allowing inbound communications, specify the CIDR appropriate for your environment.
Inbound rules allow communications on both TCP and UDP ports 443 and 4195
No outbound rules required### 2. Creating a VPC Endpoint
Next, we will create a VPC Endpoint.
From the VPC management console, create a new endpoint,
From AWS services, select the endpoint com.amazonaws.<region name>.highlander
.
Please note that the endpoint has the name highlander
, not workspaces
.
Pay attention to the endpoint name
Configure the network settings according to your environment.
Keep the "Enable DNS name" checkbox checked.
Select the security group created during the preparation step and click "Create endpoint".
Wait for a while until the status changes to "Available".
3. Configuring Amazon WorkSpaces Directory
Finally, we need to link this VPC Endpoint with the Amazon WorkSpaces directory.
From the Amazon WorkSpaces directory settings, click the edit button in the "VPC Endpoints" section.
In the edit screen, specify the created VPC Endpoint in the "Streaming endpoint" field.
Configure whether to allow PCoIP streaming according to your environment.
After editing, confirm that the endpoint settings are reflected, and all work is complete.
4. Connection Verification
Now we will verify the connection. #### 4-1. When the NAT Instance is down (in a completely closed environment)
First, we'll try connecting from a VPC that has become completely closed off after bringing down the NAT Instance.
Although not shown in the architecture diagram, we are connecting to the connection EC2 via EC2 Instance Connect Endpoint.
When launching the WorkSpaces Client in this state and checking the network status, as shown in the figure below, the result indicates that internet access is unavailable.
As mentioned earlier, since internet access is needed for authentication, attempting to connect from here will fail.
An error occurs at the registration code entry stage due to the lack of internet access#### 4-2. When NAT Instance is running (when minimal internet access is allowed)
Next, we'll start a NAT Instance to enable internet access.
This NAT Instance only allows outbound communication for HTTPS (TCP 443) and UDP port 443.
In this case, the WorkSpaces Client network status appeared as shown in the figure below.
I thought everything would be OK, but there's an error indicating that outbound communication establishment failed.
Network status showing partial OK status
Upon checking the client logs, it seems the network status check is performed against public endpoints.
In this state, I was able to connect to the WorkSpace without errors, set the registration code, and use the WorkSpace environment.
Successfully connected to WorkSpace environment without errors
This is looking good.
After checking the client logs, I found that when the VPC Endpoint is configured in the directory settings, private connection endpoint information is provided, and the client attempts to connect to those endpoints.
#
# ...omitted...
#
# Private endpoint is provided at session start
2025-08-28T04:29:37.292Z { Version: "5.29.1.5595" }: [INF] Starting WSP session using SessionId: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1, endpoints:
hostname: privatelink.prod.ap-northeast-1.WSP.aws.a2z.com, transport: QUIC, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
hostname: privatelink.prod.ap-northeast-1.WSP.aws.a2z.com, transport: QUIC, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
hostname: privatelink.prod.ap-northeast-1.WSP.aws.a2z.com, transport: TCP, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
hostname: privatelink.prod.ap-northeast-1.WSP.aws.a2z.com, transport: TCP, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
# Connection check to the provided private endpoint is attempted
2025-08-28T04:29:38.634Z { Version: "5.29.1.5595" }: [INF] Initializing session: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.635Z { Version: "5.29.1.5595" }: [DBG] Protocol new State: Initializing
2025-08-28T04:29:38.638Z { Version: "5.29.1.5595" }: [DBG] Protocol new State: Connecting
2025-08-28T04:29:38.638Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.638Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.638Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.638Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.723Z { Version: "5.29.1.5595" }: [DBG] Session window deactivated
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [DBG] Reachable endpoints after probing:
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [DBG] hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [DBG] hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [DBG] hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [DBG] hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes:
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [INF] Reachable endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [INF] Reachable endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [INF] Reachable endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
2025-08-28T04:29:38.769Z { Version: "5.29.1.5595" }: [INF] Reachable endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1
# Connecting to private endpoint
2025-08-28T04:29:38.779Z { Version: "5.29.1.5595" }: [INF] Connecting with extended endpoint configurations
2025-08-28T04:29:38.780Z { Version: "5.29.1.5595" }: [INF] Attempting to establish connection to DCV WorkSpace endpoint "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-7f73a8ab-a674-49a0-81e8-465b2e99c9f1, is reconnection: false
2025-08-28T04:29:38.782Z { Version: "5.29.1.5595" }: [INF] Connecting WorkSpace using QUIC
#
# ...omitted...
#
```When attempting to resolve the name `privatelink.prod.ap-northeast-1.highlander.aws.a2z.com` that appeared in the log, it properly returns the IP address of the VPC Endpoint that we created.

```powershell:PowerShell
# Name resolution for the private endpoint
PS C:\> nslookup privatelink.prod.ap-northeast-1.highlander.aws.a2z.com
Server: ip-10-0-0-2.ap-northeast-1.compute.internal
Address: 10.0.0.2
Non-authoritative answer:
Name: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com
Address: 10.0.21.217
```#### 4-3. Connecting from Outside AWS Environment
When I try to connect from my home, the connection is interrupted despite having no network issues whatsoever.

*Connection from home gets interrupted*
This is because internet-based connections have been disabled due to the exclusive relationship mentioned in "Limitation 3: Functional Restrictions."
Looking at the client logs, we can see it's trying to connect to a private endpoint and determining that connection is not possible.
```bash:Excerpt from home WorkSpaces client log file
#
# ...omitted...
#
2025-08-28T05:05:17.127Z { Version: "5.29.1.5595" }: [DBG] Protocol new State: Initializing
2025-08-28T05:05:17.129Z { Version: "5.29.1.5595" }: [DBG] Protocol new State: Connecting
2025-08-28T05:05:17.129Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-af1a279d-fefe-4a61-ad99-ae0c5534d9ad
2025-08-28T05:05:17.129Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: QUIC, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-af1a279d-fefe-4a61-ad99-ae0c5534d9ad
2025-08-28T05:05:17.129Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 4195, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-af1a279d-fefe-4a61-ad99-ae0c5534d9ad
2025-08-28T05:05:17.129Z { Version: "5.29.1.5595" }: [INF] Supported endpoint: "hostname: privatelink.prod.ap-northeast-1.highlander.aws.a2z.com, transport: TCP, port: 443, gatewayType: NLB, ipVersion: IPv4, additionalEndpointAttributes: ", session ID: prod-ap-northeast-1-af1a279d-fefe-4a61-ad99-ae0c5534d9ad
# Cannot connect to private endpoint
2025-08-28T05:05:17.238Z { Version: "5.29.1.5595" }: [WRN] No endpoints are reachable. A connection may not be able to be established.
#
# ...omitted...
#
```#### 4-4. Connecting to PCoIP Environment
This time we configured settings to reject connections to the PCoIP environment.
When attempting to connect to the PCoIP environment in this state, an "Invalid State Error" occurred immediately.

When trying to connect from a home environment, the same error occurred, confirming that connection to the PCoIP environment is completely blocked.
Although there was nothing clearly indicating this in the client logs, it appears that the connection fails because "destination resource does not exist" as shown in the section below.
```bash:Excerpt from WorkSpaces client log file
# When PCoIP connections are not allowed, it seems the destination resource does not exist
2025-08-28T05:29:49.187Z { Version: "5.29.1.5595" }: [DBG] PerformResourceActionRequest Type: CONNECT, Protocol: PCOIP, Session-Id: d6df764d-65e9-4abd-8882-98d2bfd6cbbc, Amzn-id: 6a775665-f37c-4930-a493-563d5f76ac35
2025-08-28T05:29:49.307Z { Version: "5.29.1.5595" }: [DBG] Received Http AllocateResourceResponse(Url: $https://ws-broker-service.ap-northeast-1.amazonaws.com/) with ()
2025-08-28T05:29:49.308Z { Version: "5.29.1.5595" }: [ERR] WorkSpacesClient.Common.UseCases.CommonGateways.WsBroker.PerformResourceAction.AllocateResourceResponse Error. Code: RESOURCE_NOT_FOUND; Message: Resource was not found.; Type: com.amazonaws.wsbrokerservice#ResourceNotFoundException
2025-08-28T05:29:49.309Z { Version: "5.29.1.5595" }: [ERR] Error while calling PerformResourceActionConnect: RESOURCE_NOT_FOUND
4-5. When Various Settings Are Disabled
While we're at it, we checked what happens when various settings are disabled while existing connections are active.
First, when we disabled PCoIP connections while an Internet-based PCoIP connection was already established, the existing connection remained available, but new connection attempts were rejected.
Next, when we disassociated the Amazon WorkSpaces and VPC Endpoint while an existing Amazon DCV connection was active, the existing connection also remained available, but new connections were routed through the Internet.
Finally, when we disassociated the relationship and then deleted the VPC Endpoint itself while an existing Amazon DCV connection was active, as expected, the existing connection was terminated simultaneously with the deletion of the VPC Endpoint.
From these results, we can see that generally existing connections are maintained.## Additional Information: Slightly Confusing Amazon WorkSpaces Related VPC Endpoints
As a bonus, I've compiled a table of Amazon WorkSpaces related VPC Endpoints (those with "workspaces" in their name) since they can be a bit confusing.
Service Name | Endpoint Name | Special Notes |
---|---|---|
Amazon WorkSpaces Stream | com.amazonaws.<region>.highlander | The endpoint added this time. Note that the name is "highlander" not "workspaces" |
Amazon WorkSpaces API operations | com.amazonaws.<region>.workspaces | Endpoint for AWS environment operation API |
Amazon WorkSpaces Instances API operations | com.amazonaws.<region>.workspaces-instances | Amazon WorkSpaces Core related functionality |
Amazon WorkSpaces Secure Browser API operations | com.amazonaws.<region>.workspaces-web | Endpoint name is based on the former name (WorkSpaces Web) |
Amazon Managed Service for Prometheus API operations | com.amazonaws.<region>.aps-workspaces | For a different service |
Please note that the term "workspaces" may be used in services other than Amazon WorkSpaces.
Conclusion
That's all for this article.
PrivateLink itself is a feature that is selective about users and usage environments, and honestly, very few people will use this functionality.
If you're considering adopting PrivateLink for Amazon WorkSpaces, I hope the content of this article will be helpful to you.
This makes sense given the mutual exclusivity with internet-based communication ↩︎