{"id":23763546,"url":"https://github.com/tomashubelbauer/webrtc-bridge","last_synced_at":"2026-05-15T20:01:28.028Z","repository":{"id":107986389,"uuid":"241187218","full_name":"TomasHubelbauer/webrtc-bridge","owner":"TomasHubelbauer","description":"An idea for serving sites from a home server through a WebRTC based frame site","archived":false,"fork":false,"pushed_at":"2022-04-14T21:33:44.000Z","size":39,"stargazers_count":0,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-31T04:21:32.560Z","etag":null,"topics":["hotp","ice","nat","otp","sdp","totp","web-server","webrtc","webrtc-data-channel"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/TomasHubelbauer.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}},"created_at":"2020-02-17T19:12:59.000Z","updated_at":"2022-12-15T06:57:17.000Z","dependencies_parsed_at":"2023-05-15T13:15:41.766Z","dependency_job_id":null,"html_url":"https://github.com/TomasHubelbauer/webrtc-bridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TomasHubelbauer/webrtc-bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fwebrtc-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fwebrtc-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fwebrtc-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fwebrtc-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomasHubelbauer","download_url":"https://codeload.github.com/TomasHubelbauer/webrtc-bridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fwebrtc-bridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33077919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["hotp","ice","nat","otp","sdp","totp","web-server","webrtc","webrtc-data-channel"],"created_at":"2024-12-31T22:12:57.929Z","updated_at":"2026-05-15T20:01:27.993Z","avatar_url":"https://github.com/TomasHubelbauer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebRTC Bridge\n\nThis project implements an idea of mine for hosting sites from a home server\nwithout directly exposing the home server to the Internet. It is based on WebRTC\ndata channels.\n\nThe idea is as follows:\n\n- Both the home server and my client (phone, laptop, …) share a static secret\n- The home server runs a WebRTC offerer and my clients run a WebRTC answerer\n- Google's free STUN service is used for WebRTC NAT traversal challenges\n- The home server initiates a WebRTC peer connection and collects SDP and ICE\n- The home server generates a TOTP code and shares the SDP+ICE using signaling\n- My signaling server https://signal.tomashubelbauer.workers.dev is used\n- The Cloudflare Workers signaling server handles CORS to enable web clients\n- The clients use the same TOTP to monitor the signaling channel for SDP+ICE\n- Upon the offer SDP+ICE find, the clients generate an answer SDP+ICE and share\n- The home server polls the signaling server for answer SDP+ICE and connects\n- Once the peer connection is established, SDP+ICE on the signal server get wiped\n- A data channel opens between the two peers and is used to serve files/pages/data\n- Currently:\n  - A DOM logger logs changes of the peer connection and the data channel states\n  - Upon connection establishment, the peers exchange timestamps periodically\n- Once finished:\n  - The data channel will be used as a web socket would, serving files/pages/data\n  - A \"frame\" HTML+JS site will be hosted on GitHub Pages hosting the web client\n  - The OTP secret will be stored in the local storage and used for the TOTP calc\n  - The frame site will download the actual SPA over the data channel\n  - One downloaded, the SPA/PWA will use the data channel for its API: RCP/CQRS\n\n## Running\n\nTo run the offerer on the server, run `node .` and wait for\n`http://localhost:8000/offerer.html` to open in a Puppeteer window.\n\nTo run the answerer on the client, use one ofthe printed link from the offerer:\n\n- Local: `http://localhost:5000/answerer.html#{secret}` (through `npx serve .`)\n- Remote: `https://tomashubelbauer.github.io/webrtc-bridge/answerer.html#{secret}`\n\nThe printed URLs include the OTP secret in the URL fragment allowing the client\nto sync with the server in case they weren't already.\n\nIf you already has an OTP secret stored with the client, you can run either the\nlocal or the remote link directly without the URL fragment:\n\n- Local: [`http://localhost:5000/answerer.html`](http://localhost:5000) (through `npx serve .`)\n- Remote: [`https://tomashubelbauer.github.io/webrtc-bridge/answerer.html`](https://tomashubelbauer.github.io/webrtc-bridge/answerer.html)\n\nIf you want to reset the OTP secret, delete `secret.js` or run `node . secret`\nand follow the running steps again.\n\n## Acknowledgements\n\nhttps://github.com/khovansky-al/web-otp-demo was used for the OTP implementation\ninspiration, specifically because it uses WebCrypto and not SHA1.js and I am\nvery thankful for not having to figure it out myself. I've extracted the essence\nI need and it works very well.\n\n## To-Do\n\n### Update ICE instead of polling only for the first SDP instance in the signal\n\nRight now ICE is collected and the SDP updated with it in the signaling channel.\nHowever, the SDP is polled only once and used immediately once it appears.\nInstead, the SDP+ICE should be polled repeatedly until the connection is\nestablished, at which point the polling should stop and the key should be\ndeleted on the signaling channel.\n\nFor now, I've tried a solution where trickle ICE is disabled forcing both peers\nto collect all ICE candidates first and only then advertise their SDP+ICE.\n\nThis still fails which might be because I need TURN? Anyway, figure out why.\n\n### Make compatible with Node using `wrtc` to not have to run in Puppeteer\n\nhttps://github.com/node-webrtc/node-webrtc\n\n### Track the worker code here and use `cf-worker-deploy` to deploy its changes.\n\n### Implement a `DELETE` method on the worker\n\nUse it instead of clearing the SDP+ICE value under the OTP once connected.\n\n### Lock the worker CORS origin to the final address of the frame site\n\n### Handle disconnects by reconnecting on the signaling server using the TOTP\n\n### Run the offerer peer on the NUC and add health checks to the script runner\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fwebrtc-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomashubelbauer%2Fwebrtc-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fwebrtc-bridge/lists"}