Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
Yuri Iozzelli
6ea07e9a65 Use CX_VERSION variable for cx.js in tinycore.html 2022-12-14 17:01:48 +01:00
Yuri Iozzelli
e8e26c8386 Allow to use an auth key and to change control URL (e.g. use headscale)
These options are passed via hash parameters in the url authKey and
controlUrl
2022-12-14 17:01:48 +01:00
Yuri Iozzelli
c8cbb9a58c Put the network logic in its own js file
index.html and tinycore.html will just both include that
2022-12-14 17:01:48 +01:00
Yuri Iozzelli
4287f26af7 update tun/ 2022-12-14 16:37:04 +01:00
9 changed files with 119 additions and 158 deletions

View file

@ -25,6 +25,18 @@ WebVM is powered by the CheerpX virtualization engine, and enables safe, sandbox
- go back to the WebVM tab. You will see your IP address in the top right
- start firing network requests!
# How to: login to Tailscale with an Auth key
- Add `#authKey=<your-key>` at the end of the URL
- Done. You don't need to manually log in anymore
It is recommended to use an ephemeral key.
# How to: login to a self-hosted Tailscale network (Headscale)
- Add `#controlUrl=<your-control-url>` at the end of the URL
- You can combine this option with `authKey` with a `&`: `#controlUrl=<url>&authKey=<key>`
# Bugs and Issues
Please use [Issues](https://github.com/leaningtech/webvm/issues) to report any bug.

View file

@ -31,81 +31,12 @@
<link rel="stylesheet" id="us-fonts-css" href="https://fonts.googleapis.com/css?family=Montserrat%3A300%2C400%2C500%2C600%2C700&amp;display=swap&amp;ver=6.0.2" media="all">
<link rel="stylesheet" href="./xterm/xterm.css" />
<link rel="stylesheet" href="./scrollbar.css" />
<script src="./xterm/xterm.js"></script>
<script src="./xterm/xterm-addon-fit.js"></script>
<script>
window.networkInterface = { bind: null, connect: null, listen: null, ready: false };
</script>
<script src="./xterm/xterm.js"></script>
<script src="./xterm/xterm-addon-fit.js"></script>
<script defer type="module">
import { State } from "/tun/tailscale_tun.js";
import { autoConf } from "/tun/tailscale_tun_auto.js";
let resolveLogin = null;
let loginPromise = new Promise((f,r) => {
resolveLogin = f;
});
const loginElem = document.getElementById("loginLink");
const statusElem = document.getElementById("networkStatus");
const loginUrlCb = (url) => {
loginElem.href = url;
loginElem.target = "_blank";
statusElem.innerHTML = "Tailscale Login";
resolveLogin(url);
};
const stateUpdateCb = (state) => {
switch(state)
{
case State.NeedsLogin:
{
break;
}
case State.Running:
{
loginElem.href = "https://login.tailscale.com/admin/machines";
break;
}
case State.Starting:
{
break;
}
case State.Stopped:
{
break;
}
case State.NoState:
{
break;
}
}
};
const netmapUpdateCb = (map) => {
const ip = map.self.addresses[0];
statusElem.innerHTML = "IP: "+ip;
};
const { listen, connect, bind, up } = await autoConf({
loginUrlCb,
stateUpdateCb,
netmapUpdateCb,
});
window.networkInterface.bind = bind;
window.networkInterface.connect = connect;
window.networkInterface.listen = listen;
window.networkInterface.ready = true;
loginElem.style.cursor = "pointer";
statusElem.style.color = "white";
loginElem.onclick = () => {
loginElem.onclick = null;
statusElem.innerHTML = "Downloading network code...";
const w = window.open("login.html", "_blank");
async function waitLogin() {
await up();
statusElem.innerHTML = "Starting login...";
const url = await loginPromise;
w.location.href = url;
}
waitLogin();
};
</script>
<script type="module" src="network.js"></script>
</head>
<body style="margin:0;height:100%;background:black;color:white;overflow:hidden; display:flex; flex-direction: column; justify-content: space-between; height: 100%;">

86
network.js Normal file
View file

@ -0,0 +1,86 @@
import { State } from "./tun/tailscale_tun.js";
import { autoConf } from "./tun/tailscale_tun_auto.js";
let params = new URLSearchParams("?"+window.location.hash.substr(1));
let authKey = params.get("authKey") || undefined;
let controlUrl = params.get("controlUrl") || undefined;
console.log(authKey, controlUrl);
let loginElemUrl = controlUrl ? null : "https://login.tailscale.com/admin/machines";
let resolveLogin = null;
let loginPromise = new Promise((f,r) => {
resolveLogin = f;
});
const loginElem = document.getElementById("loginLink");
const statusElem = document.getElementById("networkStatus");
const loginUrlCb = (url) => {
loginElem.href = url;
loginElem.target = "_blank";
statusElem.innerHTML = "Tailscale Login";
resolveLogin(url);
};
const stateUpdateCb = (state) => {
switch(state)
{
case State.NeedsLogin:
{
break;
}
case State.Running:
{
if (loginElemUrl) {
loginElem.href = loginElemUrl;
}
break;
}
case State.Starting:
{
break;
}
case State.Stopped:
{
break;
}
case State.NoState:
{
break;
}
}
};
const netmapUpdateCb = (map) => {
const ip = map.self.addresses[0];
statusElem.innerHTML = "IP: "+ip;
};
const { listen, connect, bind, up } = await autoConf({
loginUrlCb,
stateUpdateCb,
netmapUpdateCb,
authKey,
controlUrl,
});
window.networkInterface.bind = bind;
window.networkInterface.connect = connect;
window.networkInterface.listen = listen;
window.networkInterface.ready = true;
loginElem.style.cursor = "pointer";
statusElem.style.color = "white";
if (authKey) {
if (loginElemUrl) {
loginElem.href = loginElemUrl;
loginElem.target = "_blank";
}
up();
} else {
loginElem.onclick = () => {
loginElem.onclick = null;
statusElem.innerHTML = "Downloading network code...";
const w = window.open("login.html", "_blank");
async function waitLogin() {
await up();
statusElem.innerHTML = "Starting login...";
const url = await loginPromise;
w.location.href = url;
}
waitLogin();
};
}

View file

@ -30,81 +30,12 @@
<link rel="stylesheet" id="us-fonts-css" href="https://fonts.googleapis.com/css?family=Montserrat%3A300%2C400%2C500%2C600%2C700&amp;display=swap&amp;ver=6.0.2" media="all">
<link rel="stylesheet" href="./xterm/xterm.css" />
<link rel="stylesheet" href="./scrollbar.css" />
<script src="./xterm/xterm.js"></script>
<script src="./xterm/xterm-addon-fit.js"></script>
<script>
window.networkInterface = { bind: null, connect: null, listen: null, ready: false };
</script>
<script src="./xterm/xterm.js"></script>
<script src="./xterm/xterm-addon-fit.js"></script>
<script defer type="module">
import { State } from "/tun/tailscale_tun.js";
import { autoConf } from "/tun/tailscale_tun_auto.js";
let resolveLogin = null;
let loginPromise = new Promise((f,r) => {
resolveLogin = f;
});
const loginElem = document.getElementById("loginLink");
const statusElem = document.getElementById("networkStatus");
const loginUrlCb = (url) => {
loginElem.href = url;
loginElem.target = "_blank";
statusElem.innerHTML = "Tailscale Login";
resolveLogin(url);
};
const stateUpdateCb = (state) => {
switch(state)
{
case State.NeedsLogin:
{
break;
}
case State.Running:
{
loginElem.href = "https://login.tailscale.com/admin/machines";
break;
}
case State.Starting:
{
break;
}
case State.Stopped:
{
break;
}
case State.NoState:
{
break;
}
}
};
const netmapUpdateCb = (map) => {
const ip = map.self.addresses[0];
statusElem.innerHTML = "IP: "+ip;
};
const { listen, connect, bind, up } = await autoConf({
loginUrlCb,
stateUpdateCb,
netmapUpdateCb,
});
window.networkInterface.bind = bind;
window.networkInterface.connect = connect;
window.networkInterface.listen = listen;
window.networkInterface.ready = true;
loginElem.style.cursor = "pointer";
statusElem.style.color = "white";
loginElem.onclick = () => {
loginElem.onclick = null;
statusElem.innerHTML = "Downloading network code...";
const w = window.open("login.html", "_blank");
async function waitLogin() {
await up();
statusElem.innerHTML = "Starting login...";
const url = await loginPromise;
w.location.href = url;
}
waitLogin();
};
</script>
<script type="module" src="network.js"></script>
</head>
<body style="margin:0;height:100%;background:black;color:white;overflow:hidden; display:flex; flex-direction: column; justify-content: space-between; height: 100%;">
@ -319,7 +250,7 @@
var script = document.createElement('script');
script.type = 'text/javascript';
var cxFile = "https://cheerpxdemos.leaningtech.com/publicdeploy/20221125/cx.js";
var cxFile = "https://cheerpxdemos.leaningtech.com/publicdeploy/CX_VERSION/cx.js";
script.src = cxFile;
script.addEventListener("load", runInit, false);

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
tun/tailscale.wasm Executable file → Normal file

Binary file not shown.

View file

@ -51,7 +51,7 @@ export async function init() {
IpStack.input(ev.data)
};
IpStack.output(function(p){
ipn.tun.postMessage(p);
ipn.tun.postMessage(p, [p.buffer]);
});
};
setupIpStack();
@ -65,10 +65,15 @@ export async function init() {
if (localIp != newLocalIp)
{
localIp = newLocalIp;
IpStack.up({localIp, ipMap: {
try{
IpStack.up({localIp, dnsIp, ipMap: {
["127.0.0.53"]: dnsIp,
[dnsIp]: "127.0.0.53",
}});
}catch(e){
console.log(e);
debugger;
}
}
},
notifyBrowseToURL: (l) => listeners.onloginurl(l),
@ -82,6 +87,7 @@ export async function init() {
listen: IpStack.listen,
bind: IpStack.bind,
parseIP: IpStack.parseIP,
resolve: IpStack.resolve,
up: async (conf) => {
if (ipn == null) {
await lazyRunIpn();

View file

@ -1,17 +1,11 @@
import {State, init} from "./tailscale_tun.js";
export async function autoConf({loginUrlCb, stateUpdateCb, netmapUpdateCb}) {
const { listen, connect, bind, parseIP, up, down, login, logout, listeners } = await init();
const getSettings = () => {
settings.controlUrl = null;
settings.exitNodeIp = null;
settings.dnsIp = null;
settings.wantsRunning = true;
};
export async function autoConf({loginUrlCb, stateUpdateCb, netmapUpdateCb, controlUrl, authKey}) {
const { listen, connect, bind, parseIP, resolve, up, down, login, logout, listeners } = await init();
const settings = {
controlUrl: undefined,
controlUrl: controlUrl,
authKey: authKey,
exitNodeIp: undefined,
dnsIp: undefined,
wantsRunning: true,
@ -75,6 +69,7 @@ export async function autoConf({loginUrlCb, stateUpdateCb, netmapUpdateCb}) {
connect,
listen,
parseIP,
resolve,
up: async () => {
await up(settings);
},