{"id":50677106,"url":"https://github.com/chmodshubham/proto-testbed","last_synced_at":"2026-06-08T16:05:19.152Z","repository":{"id":360545313,"uuid":"1249624067","full_name":"chmodshubham/proto-testbed","owner":"chmodshubham","description":"Traffic generation between two systems using different protocols (TLS, mTLS, DTLS, QUIC, SSH, IPSec) and with classical and post-quantum cryptography.","archived":false,"fork":false,"pushed_at":"2026-06-07T12:55:37.000Z","size":316,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T14:19:51.673Z","etag":null,"topics":["dtls","ipsec","mtls","post-quantum-cryptography","quic","ssh","tls","traffic-generation"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chmodshubham.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T22:33:11.000Z","updated_at":"2026-05-28T19:10:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/chmodshubham/proto-testbed","commit_stats":null,"previous_names":["chmodshubham/proto-testbed"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chmodshubham/proto-testbed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmodshubham%2Fproto-testbed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmodshubham%2Fproto-testbed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmodshubham%2Fproto-testbed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmodshubham%2Fproto-testbed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chmodshubham","download_url":"https://codeload.github.com/chmodshubham/proto-testbed/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmodshubham%2Fproto-testbed/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34069512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dtls","ipsec","mtls","post-quantum-cryptography","quic","ssh","tls","traffic-generation"],"created_at":"2026-06-08T16:05:16.120Z","updated_at":"2026-06-08T16:05:19.143Z","avatar_url":"https://github.com/chmodshubham.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PQC Protocol Testbed\n\nTwo Ubuntu 24.04 VMs running TLS, mTLS, DTLS, QUIC, IPsec, and SSH side-by-side with a per-protocol toggle for post-quantum cryptography. `vm1` runs clients and the orchestrator; `vm2` runs servers.\n\n## Topology\n\n| Role | Hostname        | IP        | Runs                                  |\n| ---- | --------------- | --------- | ------------------------------------- |\n| vm1  | `$VM2_HOST` n/a | `$VM1_IP` | orchestrator + clients                |\n| vm2  | `$VM2_HOST`     | `$VM2_IP` | protocol servers (TLS / IKEv2 / sshd) |\n\nBoth VMs must be Ubuntu 24.04 LTS (x86_64) on the same L3-reachable network.\n\n## Protocol Support\n\n| Protocol       | PQC | KEX (PQC)              | Port (classical / PQC) | Transport |\n| -------------- | --- | ---------------------- | ---------------------- | --------- |\n| TLS 1.2 / 1.3  | Yes | X25519MLKEM768         | 4433 / 4434            | TCP       |\n| mTLS 1.2 / 1.3 | Yes | X25519MLKEM768         | 4435 / 4436            | TCP       |\n| DTLS 1.2       | No  | n/a                    | 4437                   | UDP       |\n| QUIC           | Yes | X25519MLKEM768         | 4438 / 4439            | UDP       |\n| IPsec          | Yes | ML-KEM-768 (ml plugin) | 4440 / 4441            | UDP       |\n| SSH            | Yes | mlkem768x25519-sha256  | 4442 / 4443            | TCP       |\n\n## Step 1: Prepare both VMs\n\n1. Provision two Ubuntu 24.04 hosts on the same network. Same subnet is simplest.\n2. From vm1, set up passwordless SSH to vm2 (key-based). Verify:\n   ```bash\n   ssh ubuntu@\u003cvm2-host\u003e\n   ```\n   Must succeed without password prompt. If password is unavoidable, you can set `VM2_PASSWORD` later and the testbed falls back to `sshpass`.\n3. Confirm `sudo` works on **both** VMs without password (or use `-S` style; only relevant for library builds and IPsec).\n\n## Step 2: Open ports between vm1 and vm2\n\nThe orchestrator probes TCP reachability at startup and fails fast if a port is blocked. Open the testbed range on vm2's firewall (host firewall **and** any cloud network rule):\n\n| Protocols         | Port range | Transport |\n| ----------------- | ---------- | --------- |\n| TLS, mTLS, SSH    | 4433–4443  | TCP       |\n| DTLS, QUIC, IPsec | 4437–4441  | UDP       |\n\nRestrict the source to vm1's IP or its security group; do not open to the public internet.\n\nVerify reachability from vm1:\n\n```bash\ntimeout 3 bash -c '\u003c/dev/tcp/\u003cvm2-ip\u003e/4433' \u0026\u0026 echo OPEN || echo BLOCKED\n```\n\n## Step 3: Clone the repo on both VMs\n\n```bash\ngit clone https://github.com/chmodshubham/proto-testbed proto-testbed\ncd proto-testbed\n```\n\nIdentical path on both VMs is recommended (e.g. `/home/ubuntu/proto-testbed`).\n\n## Step 4: Configure `env.sh` on vm1\n\nEdit `env.sh` and set:\n\n```bash\nexport VM2_USER=ubuntu\nexport VM2_HOST=\u003cvm2-hostname\u003e\nexport VM2_REPO=\"/home/ubuntu/proto-testbed\"   # absolute path on vm2\nexport VM1_IP=\u003cvm1-ip\u003e\nexport VM2_IP=\u003cvm2-ip\u003e\nexport VM2_PASSWORD=\"\"   # set only if vm2 SSH requires a password\n```\n\n### How to obtain each value\n\n| Variable       | Where to run | Command                                                   | Notes                                                                                                                                                      |\n| -------------- | ------------ | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `VM2_USER`     | vm2          | `whoami`                                                  | Login username used in `ssh user@host`. Usually `ubuntu` on cloud images.                                                                                  |\n| `VM2_HOST`     | vm1          | same hostname or address used in `ssh user@host` from vm1 | Private DNS, public DNS, or IP. Confirm with `ssh \"$VM2_USER@$VM2_HOST\" hostname`.                                                                         |\n| `VM2_REPO`     | vm2          | `cd ~/proto-testbed \u0026\u0026 pwd`                               | Absolute path. No tilde, no relative path.                                                                                                                 |\n| `VM1_IP`       | vm1          | `hostname -I \\| awk '{print $1}'`                         | First non-loopback IPv4. If multi-NIC, pick the one on the subnet shared with vm2.                                                                         |\n| `VM2_IP`       | vm2          | `hostname -I \\| awk '{print $1}'`                         | First non-loopback IPv4. Must be reachable from vm1 (`ping -c1 $VM2_IP` from vm1). Cert SAN is built from this value, so regenerate PKI after changing it. |\n| `VM2_PASSWORD` | vm1          | leave empty for key-based SSH                             | Triggers `sshpass` fallback when non-empty.                                                                                                                |\n\nVerify values resolve and vm2 is reachable:\n\n```bash\nsource env.sh\necho \"vm1: $VM1_IP   vm2: $VM2_IP   host: $VM2_HOST   repo: $VM2_REPO\"\nssh \"$VM2_USER@$VM2_HOST\" \"hostname; pwd; ls $VM2_REPO/env.sh\"\n```\n\nSync `env.sh` to vm2:\n\n```bash\nrsync -a env.sh \"$VM2_USER@$VM2_HOST:$VM2_REPO/\"\n```\n\nAll port variables (`PORT_TLS`, `PORT_SSH`, etc.) are defined in `env.sh` and can be overridden there.\n\n## Step 5: Build the libraries on both VMs\n\n`os-lib/` is gitignored. Each VM must build the libraries you need locally. Follow the canonical guide per library — each covers apt deps, configure flags, build, and smoke test on **both** VMs:\n\n| Library    | Build guide                              | Used by               |\n| ---------- | ---------------------------------------- | --------------------- |\n| OpenSSL    | [docs/openssl.md](docs/openssl.md)       | TLS, mTLS, DTLS, QUIC |\n| strongSwan | [docs/strongswan.md](docs/strongswan.md) | IPsec                 |\n| OpenSSH    | [docs/openssh.md](docs/openssh.md)       | SSH                   |\n\n| Library    | Version | Installed at                  |\n| ---------- | ------- | ----------------------------- |\n| OpenSSL    | 4.0     | `os-lib/install/openssl-4.0/` |\n| strongSwan | 6.0+    | `os-lib/install/strongswan/`  |\n| OpenSSH    | 10.3p1  | `os-lib/install/openssh/`     |\n\nSkip the libraries you do not plan to test (e.g. skip strongSwan if you will not run IPsec). Hardware requirements and protocol-specific build notes also appear in the per-protocol README (e.g. [protocols/tls/README.md](protocols/tls/README.md), [protocols/ipsec/README.md](protocols/ipsec/README.md)).\n\n## Step 6: Generate PKI on vm1, sync to vm2\n\nPKI is generated on vm1 only and synced to vm2. Generator: [`pki/gen.sh`](pki/gen.sh) (CA config in [`pki/ca.cnf`](pki/ca.cnf)).\n\n```bash\nsource env.sh\n./pki/gen.sh --proto all          # or --proto tls / ssh / ipsec / etc.\n```\n\nSync the generated certs and keys to vm2:\n\n```bash\nrsync -a pki/out/ \"$VM2_USER@$VM2_HOST:$VM2_REPO/pki/out/\"\n```\n\nVerify on vm2:\n\n```bash\nssh \"$VM2_USER@$VM2_HOST\" \"ls $VM2_REPO/pki/out/\"\n```\n\nPer-protocol PKI layout (what gets generated under `pki/out/` and where it is consumed) is documented in each protocol README: [TLS](protocols/tls/README.md), [mTLS](protocols/mtls/README.md), [DTLS](protocols/dtls/README.md), [QUIC](protocols/quic/README.md), [IPsec](protocols/ipsec/README.md), [SSH](protocols/ssh/README.md).\n\n## Step 7: Run the testbed\n\n```bash\n./run.sh [--proto PROTO] [--mode MODE] [--help]\n```\n\n| Flag      | Values                                         | Default |\n| --------- | ---------------------------------------------- | ------- |\n| `--proto` | `tls` `mtls` `dtls` `quic` `ipsec` `ssh` `all` | `all`   |\n| `--mode`  | `classical` `pqc` `all`                        | `all`   |\n\nExamples:\n\n```bash\n./run.sh                               # all protocols, both modes\n./run.sh --proto tls                   # TLS classical + PQC in parallel\n./run.sh --proto tls --mode classical  # TLS classical only\n./run.sh --proto ssh --mode pqc        # SSH PQC only\n./run.sh --proto ipsec --mode pqc      # IPsec PQC only (two modes cannot run together)\n./run.sh --proto all --mode classical  # all protocols, classical only\n```\n\n`run.sh` automatically:\n\n1. Installs missing apt deps for the selected protocol(s).\n2. Syncs the repo to vm2 (excludes `os-lib/` and `.git/`).\n3. Kills stale servers on vm2 holding protocol ports.\n4. Starts the server(s) on vm2 via SSH.\n5. Waits until each server is ready.\n6. Probes TCP reachability from vm1 to each server port (fails fast if blocked).\n7. Loops traffic and prints one row per connection.\n\nNotes:\n\n- DTLS has no PQC mode (DTLS 1.2; ML-KEM requires TLS 1.3).\n- IPsec cannot run classical and PQC in parallel (charon holds the kernel XFRM socket).\n- If `VM2_PASSWORD` is set, install `sshpass` on vm1 first.\n\nTo skip the TCP reachability probe (when you know the firewall is open):\n\n```bash\nTESTBED_SKIP_REACH=1 ./run.sh --proto tls\n```\n\n## Step 8: Read the output\n\n```\nTimestamp             Protocol         Conn    Key Exchange                 Cipher Suite                         Verify\n--------------------- ---------------- ------- ---------------------------- ------------------------------------ ------\n2026-05-26 00:21:14   tls/classical    #1      X25519                       TLS_AES_256_GCM_SHA384               0\n2026-05-26 00:21:14   tls/pqc          #1      X25519MLKEM768               TLS_AES_256_GCM_SHA384               0\n```\n\n- `Verify: 0` — handshake plus application-layer round-trip succeeded.\n- `Verify: FAILED` or `unknown` columns — see Troubleshooting below.\n\nPress **Ctrl-C** to stop. All servers on vm2 are torn down on exit.\n\n## Step 9: Run a single orchestrator directly (optional)\n\nBypass `run.sh` for finer control. Source `env.sh` first:\n\n```bash\nsource env.sh\n\nbash orchestrator/tls.sh   classical   # or pqc\nbash orchestrator/mtls.sh  classical   # or pqc\nbash orchestrator/dtls.sh  classical   # classical only\nbash orchestrator/quic.sh  classical   # or pqc\nbash orchestrator/ipsec.sh pqc         # or classical (not both at once)\nbash orchestrator/ssh.sh   classical   # or pqc\n```\n\nEach orchestrator starts its server on vm2, waits until ready, probes reachability, then loops traffic. Press Ctrl-C to stop. Orchestrator source: [`orchestrator/`](orchestrator/) (shared helpers in [`orchestrator/common.sh`](orchestrator/common.sh)).\n\n## Manual repo sync (rare)\n\n`run.sh` syncs automatically. To sync manually without starting a protocol:\n\n```bash\nsource env.sh\nrsync -a --delete --exclude='os-lib/' --exclude='.git/' \\\n    \"${PWD}/\" \"${VM2_USER}@${VM2_HOST}:${VM2_REPO}/\"\n```\n\nWith password auth:\n\n```bash\nRSYNC_RSH=\"sshpass -p '$VM2_PASSWORD' ssh\" rsync -a --delete \\\n    --exclude='os-lib/' --exclude='.git/' \\\n    \"${PWD}/\" \"${VM2_USER}@${VM2_HOST}:${VM2_REPO}/\"\n```\n\n## Per-protocol details\n\nEach protocol has a README covering algorithm choices, ports, key flags, and verification:\n\n| Protocol       | README                                                 |\n| -------------- | ------------------------------------------------------ |\n| TLS 1.2 / 1.3  | [protocols/tls/README.md](protocols/tls/README.md)     |\n| mTLS 1.2 / 1.3 | [protocols/mtls/README.md](protocols/mtls/README.md)   |\n| DTLS 1.2       | [protocols/dtls/README.md](protocols/dtls/README.md)   |\n| QUIC           | [protocols/quic/README.md](protocols/quic/README.md)   |\n| IPsec          | [protocols/ipsec/README.md](protocols/ipsec/README.md) |\n| SSH            | [protocols/ssh/README.md](protocols/ssh/README.md)     |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchmodshubham%2Fproto-testbed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchmodshubham%2Fproto-testbed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchmodshubham%2Fproto-testbed/lists"}