You must deploy and configure the Cloud TAP stitcher to use Cloud TAP. Netskope distributes the Cloud TAP stitcher tool as a container image. The Cloud TAP stitcher container is deployed over a cloud host instance (i.e. virtual machine) running Ubuntu 20.04 or newer versions, or RHEL 8.10 or 9.5. This tool is responsible for pulling the traffic from cloud storage, stitching back connections, doing TLS decryption, and then exporting the traffic.
You can export to .pcap format or over the wire, using VXLAN and GENEVE protocols, to external NDR tools.
Deploying the Cloud TAP Stitcher
The Cloud TAP stitcher is available as a docker image that you must run on your machine. The following is a link to the docker container for the stitcher: https://hub.docker.com/r/nsteam/cloudtap-stitcher
Refer to Cloud TAP Stitcher Host Sizing to view the machine or host resource requirement for the Cloud TAP stitcher and the desired throughput.
Use the following commands to download the docker container:
| Command | Description |
|---|---|
# download latest version | Download the latest version of the docker container. |
# download specific version [version number] | Specify the version of the docker container to download. |
ubuntu@ip-[IP address]:~$ docker images | Check the images in the docker container. |
The following is a list of commonly used arguments for running docker containers. To learn more, see the Docker help documentation.
| Arguments | Description |
|---|---|
--name | Assign a name to the container. |
-d | Run the container in the background and print the container ID. |
--rm | Automatically remove the container upon exiting. |
-v | Bind mount a volume. |
--entrypoint | Overwrite the default ENTRYPOINT of the image. |
-c | Execute a command. |
The following is an example command to run the Cloud TAP stitcher in continuous mode with /usr/bin/bash as an entrypoint to execute. The container will run in the background and will be removed automatically upon exiting. The container mounts are:
- The host (
/home/ubuntu/ctap) to the container (/ctap), which has the credential files aws.json. - The host (
/var/log) to the container (/var/log) for the stitcher.log output.
docker run --rm -d --name ns-ctap-stitcher \ -v /home/ubuntu/ctap:/ctap -v /var/log:/var/log --entrypoint "/usr/bin/bash" \ nsteam/cloudtap-stitcher \ -c 'stitcher -n --log-progress /ctap -c /ctap/aws.json --aws-region="us-west-1" --provider aws -b traffic >> /var/log/stitcher.log 2>&1'
The Cloud TAP stitcher allows you to download traffic from cloud storage (e.g., AWS S3, GCP, Azure), then converts that traffic to export or upload the packets to the local or NDR in their original or decrypted form.
Note
The format of the downloaded traffic is proprietary and any details are outside the scope of this document.
The Cloud TAP stitcher executable is installed in the container under /usr/bin/. Run docker psand locate the CONTAINER ID, then connect to the container by running docker exec -it CONTAINER ID bash. From inside the container run stitcher --help to view the full list of options. The core arguments are separated into two groups: input and output methods. Use the input options to control cloud import (e.g., cloud provider authentication. Use the output options to control output (e.g., protocol, format, etc.). When done working in the container type exit and hit enter to leave the container.
Running Modes
| Running Modes | Descriptions | Example |
|---|---|---|
| Selective retrieval | You can retrieve data from a specific timeframe. Use --start-ts and --end-ts to specify the start and end timestamps in Unix Epoch format. If no timestamps options are specified, then the Cloud TAP stitcher fetches all BLOB from the source. You can also use the human-readable --start-time, --end-time, --duration, and --tz options instead of Unix epoch timestamps. See Filtering below. | # Fetch 1 hour of data starting from Thu Jun 01 2023 22:00:00 GMT+0000 |
| One shot fetching | By default, the Cloud TAP stitcher fetches all available traffic and terminates. You can use this mode for integration testing. | # fetch and process the BLOBs once |
| Continuous fetching | This mode is supported for NDR integration. The Cloud TAP stitcher fetches all available data and then continues polling and fetching for updates. | # running continuously to fetch new data |
| Crash recovery | Use --log-progress to store the progress if a crash occurs. The Cloud TAP stitcher saves the progress file (.stitcher-progress) in the provided directory path and is a persistent directory mounted into the container. The Cloud TAP stitcher will load the previous progress and continue to run after the crash. | # runing with crash recovery progress file in /tmp direcotry |
Cloud Storage
Use the --provider option to configure the cloud providers that serve as the source of traffic for the Cloud TAP stitcher.
The Cloud TAP stitcher uses the same bucket name for both key and data by default (-b or --bucket). The Cloud TAP stitcher also uses the same credential files for both key and data by default (-c or --credentials). You can use different buckets for key and data (-k or --keylog-bucket). Optionally, you can also specify a separate credentials file for the keylog bucket (--key-credentials).
Amazon Web Services
For the data hosted in an AWS S3 bucket (--provider aws), you must provide the access credentials (--credentials), the bucket name (--bucket), and the region (--aws-region). The credentials value is a filesystem path to the JSON file in the container. To provide credentials for access to AWS S3, you can provide a JSON file on the Cloud TAP stitcher CLI with this method.
Alternatively, you can assign an IAM role to the AWS EC2 instance instead of specifying a credentials file. Once the Cloud TAP stitcher is running on the instance and you grant the IAM role the necessary permissions to access the bucket, use the --default-aws-credentials option. The AWS SDK will automatically manage authentication based on the instance’s IAM role.
docker run --rm -d --name ns-ctap-stitcher \ -v /home/ubuntu/ctap:/ctap -v /var/log:/var/log --entrypoint "/usr/bin/bash" \ nsteam/cloudtap-stitcher \ -c 'stitcher -n --log-progress /ctap -c /ctap/aws.json --aws-region="INSERT_REGION_HERE" --provider aws -b traffic >> /var/log/stitcher.log 2>&1'
If you are using AWS PrivateLink, use the following options to configure access to AWS S3:
- To access AWS S3 via PrivateLink, use
--s3-endpoint-urlfollowed by the custom AWS endpoint URL for PrivateLink (e.g.,https://bucket.vpce-xxxxxxx.s3.<region>.vpce.amazonaws.com). - To disable the virtual host-style addressing for AWS S3, use
--s3-disable-virtual-hosting. By default, this option is set to false.
Google Cloud Storage
For the data hosted in a Google Cloud Storage bucket (--provider gcp), you must provide the service account credentials (--credentials) and bucket name (--bucket) to the Cloud TAP stitcher. The credentials value is a filesystem path to the JSON file in the container.
After you grant the service account the permissions to access the bucket, when the Cloud TAP stitcher runs on the GCP VM, you can use --default-gcp-credentials instead of specifying the credential file. Google SDK automatically handles the authentication.
Microsoft Azure
For the data hosted in a Microsoft Azure Blob (--provider azure), you must provide the access credentials (--credentials) and the name of the Azure storage account (--storage-account) where your data is hosted. The credentials value is a filesystem path to the JSON file in the container. When Cloud TAP stitcher is runs on the Azure VM, and with a Managed Identify attached, it can use --default-credentials azure instead of specifying credential file. Azure SDK will handle the authentication automatically.
docker run --rm -d --name ns-ctap-stitcher \ -v /home/ubuntu/ctap:/ctap -v /var/log:/var/log --entrypoint "/usr/bin/bash" \ nsteam/cloudtap-stitcher \ -c 'stitcher -n --log-progress /ctap -c ctap/azure.json --storage-account INSERT_STORAGE_ACC_NAME_HERE --provider azure >> /var/log/stitcher.log 2>&1'
Note
When the Cloud TAP feature is enabled, a default container named ‘netskope‘ is automatically created within the specified Azure storage account.
Output Modes
The Cloud TAP stitcher can export traffic data locally or upload the data to an NDR sensor that is located in the same cloud provider and region. For NDR, the Cloud TAP stitcher uses VXLAN or Geneve encapsulation to tunnel the traffic to the sensor:
- For VXLAN, use
-vor--vxlan-hostto specify the remote VXLAN endpoint. - For Geneve, use
-gor--geneve-hostto specify the remote Geneve endpoint.
You can also export traffic from one stitcher to multiple NDR endpoints. The stitcher distributes traffic equally across the specified NDR endpoints.
- To specify multiple VXLAN endpoints, use
--vxlan-hostsfollowed by the hosts, separated by commas (--vxlan-hosts <host1>,<host2>,<host3>,etc.) - To specify multiple Geneve endpoints,
--geneve-hostsfollowed by the hosts, separated by commas (--geneve-hosts <host1>,<host2>,<host3>,etc.)
Note
The --vxlan-hosts and --geneve-hosts options are only supported for Cloud TAP in decryption mode, i.e., the Cloud TAP stitcher is exporting decrypted traffic to the NDR.
The following is an example of specifying multiple Geneve endpoints:
--geneve-hosts 192.168.10.20,192.168.10.21
Netskope-Defined Geneve Options
When you configure Geneve encapsulation (-g), the Cloud TAP stitcher uploads the following Geneve options to an NDR sensor.
| Geneve Option | Description |
|---|---|
USER_ID | If using the NSClient access method, you can use this option for Geneve to provide the Netskope-specific user identifier (email). |
SITE_ID | If using the IPSec or GRE access methods, you can use this option for Geneve to provide the Netskope-specific site identifier configured for each tunnel by the tenant. |
MTU Adjustment
(Optional) Due to the Cloud TAP stitcher using VXLAN or Geneve encapsulation to tunnel traffic, additional bytes will be added to the packet size. If necessary, you can adjust the maximum transition units (MTU) configuration to accommodate the increase in packet size and prevent IP fragmentation.
- For GCP and Azure, you can enable jumbo frames for optimal performance. This ensures that network interfaces can handle larger packet sizes with fragmentation. For more information on enabling jumbo frames, refer to the GCP or Azure documentation.
- If the exported packet size exceeds the default MTU, you can adjust the MTU of the docker host. For more information on modifying the MTU of a network interface, refer to the docker host documentation.
- You can also adjust the MTU setting of the docker container to match the MTU value of the docker host. To learn more on adjusting the MTU of the docker container, refer to the docker host documentation.
- If jumbo frames are enabled on the host, you can use the
--net=hostoption to ensure that the container respects the host’s MTU settings and help prevent performance degradation due to MTU mismatches.docker run --net=host --rm -d --name ns-ctap-stitcher -v /home/ec2-user/ctap:/ctap -v /var/log:/var/log --entrypoint /usr/bin/bash nsteam/cloudtap-stitcher -c 'stitcher -c /ctap/aws.json --aws-region=us-east-1 --provider aws -b ctap-stitcher-perf-lfs -g 172.31.89.104 > /var/log/stitcher.log 2>&1'
Note that this is one possible solution and other solutions are available. To learn more about other ways to adjust or inspect container MTU settings, refer to the docker host documentation on networking.
Transparent Mode
Some NDR vendors (e.g., ExtraHop) provide data decryption and accept original traffic and session keys. This is supported with the –-transparent option.
If you are using Geneve extensions, use the following options to control communicated time stamps:
- Use
--with-timestampsto replay the original timestamps. - Use
--with-current-timestampsto produce current timestamps at the point of export. You can use this option for testing purposes.
To separate the ExtraHop management interface and data capture interface for higher throughput, use the following options to push the session keys and data to different interfaces:
- Use
--extrahop-prodto specify the hostname for uploading ExtraHop NDR data. - Use
--extrahop-management-hostto specify the hostname for uploading ExtraHop session keys.
Decryption Mode
By default, the traffic processed by the Cloud TAP stitcher is decrypted. You can upload the traffic directly to an NDR that accepts decrypted traffic. To export decrypted traffic with NDR, use the --with-decrypted option.
stitcher -c aws.json --provider aws --aws-region="us-west-1" -b traffic -g x.x.x.x -n \
--with-timestamps --with-decrypted
Filtering
The Cloud TAP stitcher can apply traffic filters when processing traffic, allowing for fine-grained slice exports. Each filter value is a pcap expression. For example, you can retrieve a slice of traffic from a given time and source.
# Fetch 1 hour of data starting from Thu Jun 01 2023 22:00:00 GMT+0000 for a single user stitcher --provider gcp -b traffic \ --start-ts 1685656800 --end-ts 1685660400 \ --export-filter "host 1.2.3.4 and tcp port 443" \ -e export.pcap
You can also filter an export by user or site. Use –user-filter followed by an email address to export traffic for a specific user. Use –site-filter followed by a site identifier to export traffic for a specific branch office or tunnel. These filters apply to regular pcap export and decrypted NDR streaming only. They don’t apply to raw pcap export (–re/-r) or transparent NDR streaming, since the user and site metadata they rely on, is only available after decryption.
To specify a time range in human-readable format instead of Unix epoch time, use –start-time and –end-time with an ISO 8601 timestamp, or –start-time combined with –duration to specify a length such as 1h. Use –tz to set the time zone offset for these values.
stitcher –provider aws -b traffic –user-filter “user@company.com” –start-time “2026-07-01T00:00:00” –duration 1h –tz “+08:00” -e export.pcap
Generate PCAP using Cloud TAP Stitcher
Cloud TAP Stitcher fetches the traffic blobs from cloud storage and can generate pcap which is stored:
- Either on local disk of virtual machine where Cloud TAP Stitcher runs
- Or in specified cloud storage location (Beta).
The following Cloud TAP Stitcher CLI options provide these high-level capabilities:
- Provide size estimate of pcap archive before actually generating pcap.
- Provide filters for user and site (IPsec/GRE) for limiting the size of pcap
- Upload archive of pcap file(s) directly to your cloud storage bucket . pcap can also be written to the local disk.
- Allow customization of maximum size of individual pcap file within the archive.
- Sequencing of packets belonging to a 5-tuple flow within each pcap file.
- Human-readable start-time and end-time alongwith duration for usability.
| CLI Options | Description |
|---|---|
| --pcap-estimate | Prints an estimated output size and file count based on a listing of the source data, without downloading or processing any traffic, then exits. To actually generate the pcap, run the command without the pcap-estimate flag option. |
| --pcap-merge-by-flow | Merges the per-thread pcap files into a single archive, grouping packets by flow. The archive is created only when pcap needs to be uploaded back to the cloud. See the below mentioned –pcap-upload options for the same. |
| --pcap-merge-max-size | Sets the maximum size, in MB, for each pcap file inside the merged archive. The default is 200 MB. |
| --pcap-upload-bucket | Sets the destination cloud storage bucket for the merged archive. |
| --pcap-upload-provider | Sets the cloud provider for the upload destination. Accepts aws, gcp, or azure. |
| --pcap-upload-default-credentials | Uses the host's IAM role or managed identity to authenticate to the upload destination, so you don't need a separate credentials file. |
| --pcap-manifest | Includes a manifest.json file inside the archive that records the source data, filters, and flows used to produce each pcap file. Enabled by default. |
| --tz | Sets the timezone offset for --start-time and --end-time input, and for the output filename, in ±HH:MM format (for example, +08:00 or -04:00). Defaults to UTC. |
| --user-filter | Filters the export to traffic from a specific user, identified by email address. Applies to regular pcap export and decrypted NDR streaming only; not compatible with raw export (--raw-export) or transparent NDR streaming. |
| --site-filter | Filters the export to traffic from a specific site. Identified by remote IP for GRE tunnels, or remote IP plus tunnel identity for IPSec tunnels. Applies to regular pcap export and decrypted NDR streaming only; not compatible with raw export (--raw-export) or transparent NDR streaming. |
| --start-time | Sets the start of the export time range using a human-readable timestamp, for example 2026-05-26T18:00:00. Use --tz to set the timezone. Can't be used together with --start-ts. |
| --end-time | Sets the end of the export time range using a human-readable timestamp. Use --tz to set the timezone. Can't be used together with --end-ts or --duration. |
| --duration | Sets the length of the export window, for example 5m, 1h, or 90s, instead of specifying an end time. Used together with --start-time or –start-ts. Can't be used together with --end-time or --end-ts. |
| --pcap-upload-storage-account | Sets the Azure Storage Account name for the upload destination. Required when --pcap-upload-provider is azure. |
| --pcap-upload-aws-region | Sets the AWS region for the upload destination bucket. Optional, defaults to the value of --aws-region if not set. Use this when the upload bucket is in a different region than the source bucket. |
| --pcap-upload-credentials | Credentials file for the upload destination. Optional if using --pcap-upload-default-credentials. |
The merged archive uses store mode, meaning the files are packaged together without compression. It also includes a manifest.json file that records which source data, filters, and flows produced each pcap file, useful for audits and troubleshooting.
Following are examples on how to generate pcap for various scenarios:
-
Scenario 1: Acme customer wants pcap for a specific user during an incident
> “We need to see what user john@Acme.com was doing between 2pm-3pm today”
Step 1: estimate size first (prints and exits)
$ stitcher --provider aws --default-credentials aws -b Acme-traffic-bucket --aws-region us-east-1 --start-time "2026-05-26T14:00:00" --duration 1h --tz "-04:00" --user-filter "john@Acme.com" -e /output/ --pcap-merge-by-flow --pcap-estimate
Step 2: run the actual export and upload
$ stitcher --provider aws --default-credentials aws -b Acme-traffic-bucket --aws-region us-east-1 --start-time "2026-05-26T14:00:00" --duration 1h --tz "-04:00" --user-filter "john@Acme.com" -e /output/ --pcap-merge-by-flow --pcap-upload-bucket Acme-pcap-output --pcap-upload-default-credentials aws
-
Scenario 2: Network engineer troubleshooting connectivity to a specific host
> “Show me all traffic to 10.0.0.1 port 443 in the last hour from NYC”
$ stitcher --provider gcp -c /ctap/gcp.json -b my-bucket --start-time "2026-05-26T10:00:00" --duration 1h --origin-filter "US-NYC*" --export-filter "host 10.0.0.1 and port 443" -e /output/ --pcap-merge-by-flow --pcap-upload-bucket my-pcap-bucket --pcap-upload-provider gcp --pcap-upload-credentials /ctap/gcp-upload.json
-
Scenario 3: Filter by branch office (IPSec tunnel) for compliance
> “Export all traffic from our NYC branch office in the last 2 hours”
$ stitcher --provider aws --default-credentials aws -b company-bucket --aws-region us-east-1 --start-time "2026-05-26T08:00:00" --duration 2h --tz "-04:00" --site-filter "10.1.2.3:nyc-branch" -e /output/ --pcap-merge-by-flow --pcap-upload-bucket compliance-pcap --pcap-upload-default-credentials aws
-
Scenario 4: Estimate before export (large time range)
> “How big would a 6-hour export be? Let me check before committing”
$ stitcher --provider gcp -c /ctap/gcp.json -b my-bucket --start-time "2026-05-26T00:00:00" --duration 6h --origin-filter NSKP -e /output/ --pcap-merge-by-flow --pcap-estimate
-
Scenario 5: Azure upload with storage account credentials
> “Upload pcap to Azure blob storage for compliance archiving”
$ stitcher --provider aws --default-credentials aws -b Acme-traffic-bucket --aws-region us-east-1 --start-time "2026-05-26T14:00:00" --duration 1h -e /output/ --pcap-merge-by-flow --pcap-upload-bucket my-pcap-container --pcap-upload-provider azure --pcap-upload-storage-account myaccount --pcap-upload-credentials /ctap/azure.json
-
Scenario 6: Simple local export without cloud upload
$ stitcher --provider gcp -c /ctap/gcp.json -b my-bucket --start-time "2026-05-26T18:00:00" --duration 5m --tz "+08:00" --origin-filter NSKP -e /output/ --pcap-merge-by-flow
Keep the following in mind before using this capability:
- If uploading pcap back to cloud, ensure to have twice your estimated pcap size in disk space, since Stitcher writes intermediate pcap files before building the final archive.
- With AWS, the maximum size of uploaded pcap archives is limited to 80 GB.
- If the upload fails, Stitcher keeps the local archive so you don’t lose data, but you need to re-run the export manually. Automatic retry isn’t available yet.
Scaling with Multiple Cloud TAP Stitcher Instances
Tip
Prior to configuring multiple Cloud TAP stitcher instances, Netskope recommends planning your values to avoid overlap and ensure balanced load distribution. You must also ensure that each instance is responsible for a distinct subset of traffic. Distributing copied traffic from one Netskope point of presence (POP) across multiple Cloud TAP stitcher instances is not supported.
You can distribute traffic copied from multiple origins (e.g., Netskope POPs) across multiple instances to achieve the desired scale.
To select the traffic sources or POPs to process, you can use wildcards with the --origin-filter option. Alternatively, you can use the --origin-filter-regex option to create more complex match patterns (e.g., including or excluding POPs) with regular expression syntax.
Important
To avoid compatibility issues between the --origin-filter and --origin-filter-regex options, you must use only one option.
Wildcards
The following are examples of wildcards you can use with the --origin-filter option.
| Wildcards | Descriptions |
|---|---|
--origin-filter US-NYC* | This wildcard allows the Cloud TAP stitcher to process all POPs that start with US-NYC. |
--origin-filter *NYC* | This wildcard allows the Cloud TAP stitcher to process all POPs that contain NYC. |
--origin-filter UK-* | This wildcard allows the Cloud TAP stitcher to process all POPs in the UK. |
stitcher --provider gcp -c gcp.json -b traffic --origin-filter US-NYC* --extrahop-management-host 10.138.0.40 --extrahop-prod 192.168.10.2 | This wildcard allows the Cloud TAP stitcher to perform selective retrieval by data center. |
The following is an example of using multiple wildcards to distribute the load across multiple instances.
| Instances | Wildcards |
|---|---|
| Instance 1 | stitcher --provider gcp -c gcp.json -b traffic --origin-filter US-* --extrahop-management-host 10.138.0.40 --extrahop-prod 192.168.10.2 |
| Instance 2 | stitcher --provider gcp -c gcp.json -b traffic --origin-filter IN-* --extrahop-management-host 10.138.0.40 --extrahop-prod 192.168.10.2 |
| Instance 3 | stitcher --provider gcp -c gcp.json -b traffic --origin-filter UK-* --extrahop-management-host 10.138.0.40 --extrahop-prod 192.168.10.2 |
Regex
The following are examples of regex patterns you can use with the --origin-filter-regex option.
| Regex Patterns | Description |
|---|---|
--origin-filter-regex ^(?!.(?:YYZ1|YMQ1|NYC1|PAR1)).$ | With this pattern, the Cloud TAP stitcher excludes (i.e., doesn’t process) traffic from any of the following POPs: YYZ1, YMQ1, NYC1, or PAR1. |
--origin-filter-regex ^.*(?:YYZ1|YMQ1|NYC1|PAR1).*$ | With this pattern, the Cloud TAP stitcher processes traffic from any of the following POPs: YYZ1, YMQ1, NYC1, or PAR1. |
Cloud TAP Stitcher Host Sizing
The following tables provide the Cloud TAP stitcher throughput with respect to different host instance types for each supported cloud provider.
Note
Netskope collected the following throughput numbers while testing with specific test profiles, regions, and file sizes.
For the Cloud TAP stitcher, Netskope recommends at least 80 GB of disk space, but you might require more depending on your retention strategy (e.g., a higher-throughput deployment can require more than 100 GB). To determine the CPU and memory required for the Cloud TAP stitcher, refer to your cloud storage provider’s official documentation. If you plan to use the pcap merge and upload options described above, budget disk space at roughly twice your estimated export size to account for the intermediate files.
Amazon Web Services
| Host Instance Type | Cloud Tap Stitcher Throughput (Gbps) |
|---|---|
| c5n.2xlarge | 1 |
| c5n.4xlarge | 2 |
| c5n.9xlarge | 4 |
| c5.18xlarge | 8 |
Google Cloud
| Host Instance Type | Cloud TAP Stitcher Throughput (Gbps) |
|---|---|
| c3-standard-8 | 1 |
| c3-standard-22 | 4 |
| c3-standard-44 | 6 |
| c3-standard-88 | 8 |
Microsoft Azure
| Host Instance Type | Cloud TAP Stitcher Throughput (Gbps) |
|---|---|
| Standard_F8s_v2 | 1 |
| Standard_F16s_v2 | 2 |
| Standard_F32s_v2 | 4 |
| Standard_F64s_v2 | 8 |

