dockerfile/examples/omnivore/content-fetch/readabilityjs/test/test-pages/computerenhance.com/source.html

1236 lines
195 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="norton-safeweb-site-verification" content="24usqpep0ejc5w6hod3dulxwciwp0djs6c6ufp96av3t4whuxovj72wfkdjxu82yacb7430qjm8adbd5ezlt4592dq4zrvadcn9j9n-0btgdzpiojfzno16-fnsnu7xd" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<meta name="author" content="Casey Muratori" />
<meta property="og:url" content="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp" />
<link rel="canonical" href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp" />
<link rel="shortcut icon" href="https://substackcdn.com/icons/substack/favicon.ico" />
<link rel="icon" type="image/png" sizes="16x16" href="https://substackcdn.com/icons/substack/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="https://substackcdn.com/icons/substack/favicon-32x32.png" />
<link rel="apple-touch-icon" sizes="57x57" href="https://substackcdn.com/icons/substack/apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="60x60" href="https://substackcdn.com/icons/substack/apple-touch-icon-60x60.png" />
<link rel="apple-touch-icon" sizes="72x72" href="https://substackcdn.com/icons/substack/apple-touch-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="https://substackcdn.com/icons/substack/apple-touch-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="https://substackcdn.com/icons/substack/apple-touch-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="https://substackcdn.com/icons/substack/apple-touch-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="https://substackcdn.com/icons/substack/apple-touch-icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="https://substackcdn.com/icons/substack/apple-touch-icon-152x152.png" />
<link rel="apple-touch-icon" sizes="167x167" href="https://substackcdn.com/icons/substack/apple-touch-icon-167x167.png" />
<link rel="apple-touch-icon" sizes="180x180" href="https://substackcdn.com/icons/substack/apple-touch-icon-180x180.png" />
<link rel="apple-touch-icon" sizes="1024x1024" href="https://substackcdn.com/icons/substack/apple-touch-icon-1024x1024.png" />
<title>
No really, why can't we have raw UDP in JavaScript?
</title>
<link rel="alternate" type="application/rss+xml" href="/feed" title="Computer, Enhance!" />
<style>
<![CDATA[
/*https://fonts.googleapis.com/css?family=Spectral:400,400i,600,600i*/
/* cyrillic */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 400;
src: local('Spectral Italic'), local('Spectral-Italic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCt-xNNww_2s0amA9M8on7mTNmnUHowCw.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
font-display: fallback;
}
/* vietnamese */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 400;
src: local('Spectral Italic'), local('Spectral-Italic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCt-xNNww_2s0amA9M8onXmTNmnUHowCw.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
font-display: fallback;
}
/* latin-ext */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 400;
src: local('Spectral Italic'), local('Spectral-Italic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCt-xNNww_2s0amA9M8onTmTNmnUHowCw.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
font-display: fallback;
}
/* latin */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 400;
src: local('Spectral Italic'), local('Spectral-Italic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCt-xNNww_2s0amA9M8onrmTNmnUHo.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
font-display: fallback;
}
/* cyrillic */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 600;
src: local('Spectral SemiBold Italic'), local('Spectral-SemiBoldItalic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCu-xNNww_2s0amA9M8qqXCWfCFXVAKArdqqQ.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
font-display: fallback;
}
/* vietnamese */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 600;
src: local('Spectral SemiBold Italic'), local('Spectral-SemiBoldItalic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCu-xNNww_2s0amA9M8qqXCWfuFXVAKArdqqQ.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
font-display: fallback;
}
/* latin-ext */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 600;
src: local('Spectral SemiBold Italic'), local('Spectral-SemiBoldItalic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCu-xNNww_2s0amA9M8qqXCWfqFXVAKArdqqQ.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
font-display: fallback;
}
/* latin */
@font-face {
font-family: 'Spectral';
font-style: italic;
font-weight: 600;
src: local('Spectral SemiBold Italic'), local('Spectral-SemiBoldItalic'), url(https://fonts.gstatic.com/s/spectral/v5/rnCu-xNNww_2s0amA9M8qqXCWfSFXVAKArc.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
font-display: fallback;
}
/* cyrillic */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 400;
src: local('Spectral Regular'), local('Spectral-Regular'), url(https://fonts.gstatic.com/s/spectral/v5/rnCr-xNNww_2s0amA9M9knjsS_ulYHs.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
font-display: fallback;
}
/* vietnamese */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 400;
src: local('Spectral Regular'), local('Spectral-Regular'), url(https://fonts.gstatic.com/s/spectral/v5/rnCr-xNNww_2s0amA9M2knjsS_ulYHs.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
font-display: fallback;
}
/* latin-ext */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 400;
src: local('Spectral Regular'), local('Spectral-Regular'), url(https://fonts.gstatic.com/s/spectral/v5/rnCr-xNNww_2s0amA9M3knjsS_ulYHs.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
font-display: fallback;
}
/* latin */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 400;
src: local('Spectral Regular'), local('Spectral-Regular'), url(https://fonts.gstatic.com/s/spectral/v5/rnCr-xNNww_2s0amA9M5knjsS_ul.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
font-display: fallback;
}
/* cyrillic */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 600;
src: local('Spectral SemiBold'), local('Spectral-SemiBold'), url(https://fonts.gstatic.com/s/spectral/v5/rnCs-xNNww_2s0amA9vmtm3FafaPWnIIMrY.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
font-display: fallback;
}
/* vietnamese */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 600;
src: local('Spectral SemiBold'), local('Spectral-SemiBold'), url(https://fonts.gstatic.com/s/spectral/v5/rnCs-xNNww_2s0amA9vmtm3OafaPWnIIMrY.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
font-display: fallback;
}
/* latin-ext */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 600;
src: local('Spectral SemiBold'), local('Spectral-SemiBold'), url(https://fonts.gstatic.com/s/spectral/v5/rnCs-xNNww_2s0amA9vmtm3PafaPWnIIMrY.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
font-display: fallback;
}
/* latin */
@font-face {
font-family: 'Spectral';
font-style: normal;
font-weight: 600;
src: local('Spectral SemiBold'), local('Spectral-SemiBold'), url(https://fonts.gstatic.com/s/spectral/v5/rnCs-xNNww_2s0amA9vmtm3BafaPWnII.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
font-display: fallback;
}
]]>
</style>
<style>
<![CDATA[
:root{--background_pop:#FF6B00;--cover_bg_color:#FFFFFF;--background_pop_darken:#e66000;--print_on_pop:#ffffff;--border_subtle:rgba(204, 204, 204, 0.5);--background_subtle:rgba(255, 233, 217, 0.4);--print_pop:#ff6b00;--cover_print_primary:#1a1a1a;--cover_print_secondary:#757575;--cover_border_color:#ff6b00;--font_family_body_preset:Lora,sans-serif;--font_weight_body_preset:400;--font_size_body_offset:1px;--font_preset_body:fancy_serif;--web_bg_color:#ffffff;--background_contrast_1:#f7f7f7;--background_contrast_2:#ebebeb;--background_contrast_3:#d6d6d6;--background_contrast_4:#b8b8b8;--background_contrast_5:#9a9a9a;--background_contrast_pop:rgba(255, 107, 0, 0.4);--input_background:#ffffff;--cover_input_background:#ffffff;--tooltip_background:#191919;--web_bg_color_h:0;--web_bg_color_s:0%;--web_bg_color_l:100%;--print_on_web_bg_color:#1a1a1a;--print_secondary_on_web_bg_color:#767676;--selected_comment_background_color:#fdf9f3;--background_pop_rgb:255, 107, 0;}
]]>
</style>
<link rel="stylesheet" href="https://substackcdn.com/theme/main.css?v=d8d6f155f6f5a6225e9ba379cba495a6" />
<link rel="stylesheet" type="text/css" href="https://substackcdn.com/min/main.css?v=12f9-181d0ca8818" />
<meta property="og:type" content="article" data-preact-helmet="true" />
<meta name="theme-color" content="#ffffff" data-preact-helmet="true" />
<meta property="og:title" content="No really, why can't we have raw UDP in JavaScript?" data-preact-helmet="true" />
<meta property="twitter:title" content="No really, why can't we have raw UDP in JavaScript?" data-preact-helmet="true" />
<meta name="description" content="In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS." data-preact-helmet="true" />
<meta property="og:description" content="In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS." data-preact-helmet="true" />
<meta property="twitter:description" content="In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS." data-preact-helmet="true" />
<meta property="og:image" content="https://substackcdn.com/image/fetch/w_1200,h_600,c_limit,f_jpg,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg" data-preact-helmet="true" />
<meta property="twitter:image" content="https://substackcdn.com/image/fetch/w_1200,h_600,c_limit,f_jpg,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg" data-preact-helmet="true" />
<meta property="twitter:card" content="summary_large_image" data-preact-helmet="true" />
<meta http-equiv="origin-trial" content="A9wkrvp9y21k30U9lU7MJMjBj4USjLrGwV+Z8zO3J3ZBH139DOnCv3XLK2Ii40S94HG1SZ/Zeg2GSHOD3wlWngYAAAB7eyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGV0YWdtYW5hZ2VyLmNvbTo0NDMiLCJmZWF0dXJlIjoiUHJpdmFjeVNhbmRib3hBZHNBUElzIiwiZXhwaXJ5IjoxNjYxMjk5MTk5LCJpc1RoaXJkUGFydHkiOnRydWV9" />
<style>
<![CDATA[
#nojs-banner {
position: fixed;
bottom: 0;
left: 0;
padding: 16px 16px 16px 32px;
width: 100%;
box-sizing: border-box;
background: red;
color: white;
font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 13px;
line-height: 13px;
}
#nojs-banner a {
color: inherit;
text-decoration: underline;
}
]]>
</style>
</head>
<body>
<div id="entry">
<div id="main" class="main typography use-theme-bg">
<iframe src="https://substack.com/channel-frame" class="channel-frame" width="0" height="0"></iframe>
<div class="main-menu animated">
<div class="main-menu-content" style="top: -65px; position: fixed;">
<div class="topbar">
<div class="topbar-content">
<div class="navbar-logo-container no-logo" style="width: 172.828px;"></div>
<h1 class="navbar-title">
<a class="navbar-title-link" href="https://www.computerenhance.com">Computer, Enhance!</a>
</h1>
<div class="navbar-buttons">
<button data-testid="noncontributor-cta-button" class="button primary subscribe-cta subscribe-btn" type="button" tabindex="0">Subscribe</button><button native="true" class="button sign-in-link outline-grayscale" type="button" tabindex="0">Sign in</button>
</div>
</div>
</div>
</div>
<div class="topbar-spacer"></div>
</div>
<div>
<script type="application/ld+json">
<![CDATA[
{"@context":"http://schema.org","@type":"NewsArticle","url":"https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp","mainEntityOfPage":"https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp","headline":"No really, why can't we have raw UDP in JavaScript?","description":"In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS.","image":[{"@type":"ImageObject","url":"https://substackcdn.com/image/fetch/h_600,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg"}],"datePublished":"2022-07-05T10:58:16+08:00","dateModified":"2022-07-05T10:58:16+08:00","isAccessibleForFree":true,"hasPart":{},"author":{"@type":"Person","name":"Casey Muratori","url":"https://substack.com/profile/11696674-casey-muratori","sameAs":["https://twitter.com/cmuratori"]},"publisher":{"@type":"Organization","name":"Computer, Enhance!","sameAs":["https://twitter.com/cmuratori"]}}
]]>
</script>
<div class="single-post-container">
<div class="container">
<div class="single-post">
<article class="typography newsletter-post post">
<div role="dialog" class="modal typography out gone share-dialog popup">
<div class="modal-table">
<div class="modal-row">
<div class="modal-cell modal-content no-fullscreen">
<div class="container">
<button data-testid="close-modal" class="button modal-btn modal-exit-btn no-margin" type="button" tabindex="0"><svg role="img" width="20" height="20" viewbox="0 0 20 20" fill="none" stroke-width="1" stroke="#666666" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M15 5L5 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 5L15 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</g></svg></button>
<div class="share-dialog-title">
Share this post
</div>
<div class="social-preview-box post">
<div class="social-image-box">
<img src="https://substackcdn.com/image/fetch/w_120,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg" />
</div>
<div class="social-labels">
<div class="social-title">
No really, why can't we have raw UDP in JavaScript?
</div>
<div class="social-subtitle">
www.computerenhance.com
</div>
</div>
</div>
<div class="share-action-row">
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="20" height="16" viewbox="0 0 20 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1303 0.000379039C10.9833 -0.00959082 9.87819 0.431464 9.05309 1.22855L9.04556 1.23593L7.79145 2.48303C7.50587 2.767 7.50453 3.22877 7.78844 3.51441C8.07235 3.80004 8.53401 3.80139 8.81959 3.51741L10.0698 2.27423C10.6194 1.74503 11.3546 1.45229 12.1177 1.45892C12.8824 1.46556 13.6139 1.77236 14.1546 2.31323C14.6954 2.8541 15.0021 3.58577 15.0087 4.35065C15.0154 5.11353 14.7229 5.84857 14.1943 6.39829L12.0116 8.58145L12.0115 8.58155C11.7159 8.87739 11.36 9.10617 10.9682 9.25237C10.5764 9.39857 10.1577 9.45878 9.74051 9.42889C9.32337 9.39901 8.91752 9.27975 8.55051 9.07918C8.1835 8.87862 7.8639 8.60146 7.6134 8.26649C7.3722 7.94396 6.91526 7.87807 6.5928 8.11933C6.27034 8.36059 6.20447 8.81763 6.44567 9.14016C6.82142 9.64261 7.30082 10.0584 7.85134 10.3592C8.40186 10.66 9.01062 10.8389 9.63634 10.8838C10.2621 10.9286 10.8901 10.8383 11.4779 10.619C12.0656 10.3997 12.5994 10.0565 13.0429 9.61274L15.2302 7.42494L15.2391 7.4159C16.036 6.59062 16.4769 5.48529 16.467 4.33797C16.457 3.19066 15.9969 2.09316 15.1858 1.28185C14.3746 0.470545 13.2774 0.0103489 12.1303 0.000379039ZM7.29806 5.11625C6.67234 5.07142 6.0443 5.16173 5.45654 5.38103C4.86882 5.60031 4.33502 5.94355 3.89153 6.38727L1.70423 8.57506L1.69534 8.5841C0.898438 9.40939 0.457483 10.5147 0.467451 11.662C0.477418 12.8094 0.937512 13.9069 1.74864 14.7182C2.55976 15.5295 3.65701 15.9897 4.80407 15.9996C5.95113 16.0096 7.05622 15.5685 7.88132 14.7715L7.89035 14.7626L9.13717 13.5155C9.42192 13.2307 9.42192 12.7689 9.13717 12.4841C8.85243 12.1993 8.39077 12.1993 8.10602 12.4841L6.86392 13.7265C6.31432 14.2552 5.57945 14.5477 4.81675 14.5411C4.05204 14.5344 3.32054 14.2276 2.77979 13.6868C2.23904 13.1459 1.93231 12.4142 1.92566 11.6494C1.91904 10.8865 2.21146 10.1514 2.74011 9.60172L4.92287 7.41846C5.21854 7.12262 5.57437 6.89384 5.96621 6.74763C6.35805 6.60143 6.77674 6.54123 7.19389 6.57111C7.61104 6.601 8.01688 6.72026 8.38389 6.92082C8.75091 7.12138 9.0705 7.39855 9.32101 7.73352C9.56221 8.05605 10.0191 8.12194 10.3416 7.88068C10.6641 7.63942 10.7299 7.18238 10.4887 6.85985C10.113 6.3574 9.63359 5.94165 9.08307 5.64081C8.53255 5.33997 7.92378 5.16107 7.29806 5.11625Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Copy link</button>
</div>
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="20" height="16" viewbox="0 0 20 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1524 0.286815C12.9848 -0.0318829 13.8948 -0.0864749 14.7592 0.130489C15.462 0.306912 16.107 0.655903 16.6376 1.14249C17.3169 0.89658 17.961 0.560161 18.5523 0.141743C18.7998 -0.0334198 19.1301 -0.0365939 19.381 0.133779C19.6318 0.304152 19.7507 0.612306 19.6791 0.907C19.4028 2.04538 18.8458 3.09393 18.0616 3.95753C18.0757 4.09811 18.083 4.23936 18.0835 4.3808L18.0835 4.38319C18.0835 9.29757 15.7264 12.8962 12.3452 14.7015C8.98147 16.4975 4.67843 16.4794 0.840591 14.3406C0.546545 14.1767 0.403384 13.8324 0.49452 13.5084C0.585656 13.1843 0.887269 12.9652 1.22363 12.9786C2.65157 13.0356 4.0647 12.7377 5.34034 12.12C4.06579 11.3575 3.15922 10.4438 2.53674 9.45782C1.73519 8.18825 1.43205 6.84263 1.37719 5.63204C1.32248 4.42456 1.51372 3.33632 1.71513 2.55507C1.81628 2.16276 1.92118 1.84328 2.00191 1.61926C2.04232 1.50714 2.0768 1.41859 2.10191 1.35643C2.11446 1.32534 2.12469 1.30081 2.13215 1.2832L2.14123 1.26201L2.14412 1.25538L2.14514 1.25307L2.14553 1.25217C2.1457 1.25179 2.14586 1.25144 2.81079 1.54604L2.14586 1.25144C2.25213 1.01158 2.47934 0.847546 2.74046 0.822176C3.00157 0.796805 3.25612 0.914031 3.40657 1.12894C4.15428 2.19698 5.15353 3.06271 6.31515 3.64923C7.26519 4.12892 8.2998 4.40971 9.35623 4.47759V4.41217C9.34536 3.52161 9.60685 2.64886 10.1058 1.91153C10.6058 1.17278 11.3201 0.605503 12.1524 0.286815ZM3.09343 3.03841C2.9284 3.71356 2.78659 4.6028 2.83025 5.5662C2.8764 6.58479 3.12882 7.67102 3.76666 8.68131C4.40153 9.68688 5.44569 10.6611 7.14733 11.4198C7.38821 11.5272 7.55207 11.7566 7.57557 12.0192C7.59906 12.2819 7.47851 12.5367 7.26052 12.6852C6.28428 13.3499 5.20629 13.8343 4.07717 14.1236C6.75502 14.8865 9.46059 14.5928 11.6602 13.4184C14.5413 11.8801 16.6285 8.79158 16.6289 4.38467C16.6283 4.20406 16.611 4.0239 16.5772 3.84652C16.5318 3.60859 16.6079 3.3637 16.7801 3.19336C17.0303 2.94581 17.2553 2.67591 17.4527 2.38779C17.1883 2.49441 16.9189 2.58923 16.6453 2.67187C16.3709 2.75477 16.0733 2.6687 15.8855 2.45208C15.4964 2.00326 14.9795 1.68547 14.4051 1.54127C13.8306 1.39708 13.2258 1.43333 12.6725 1.6452C12.1191 1.85707 11.6436 2.23446 11.3105 2.72674C10.9773 3.21904 10.8028 3.80236 10.8107 4.39779L10.8108 4.40751H10.8108V5.21813C10.8108 5.61242 10.4966 5.9349 10.1024 5.94515C8.56202 5.98522 7.03575 5.6425 5.65956 4.94765C4.69805 4.46217 3.83071 3.81535 3.09343 3.03841Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Twitter</button>
</div>
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="16" height="17" viewbox="0 0 16 17" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M10.6543 1.38723C10.3533 0.960814 9.95383 0.61341 9.48976 0.374567C9.02902 0.137956 8.51908 0.0130716 8.00115 0.0100098C7.86087 0.0101844 7.72354 0.0502687 7.60519 0.125581C7.48684 0.200893 7.39237 0.308324 7.3328 0.435326L5.00368 5.67077H3.029C2.72335 5.66964 2.42059 5.73003 2.13876 5.84833C1.85692 5.96663 1.60177 6.14043 1.38849 6.35938C1.16707 6.57502 0.991841 6.83346 0.873459 7.11897C0.755078 7.40447 0.696022 7.71108 0.699885 8.02014V13.691C0.699885 14.3087 0.945273 14.9012 1.38207 15.338C1.81886 15.7747 2.41128 16.0201 3.029 16.0201H13.348C13.8951 16.021 14.425 15.8283 14.8438 15.4762C15.2626 15.1241 15.5434 14.6352 15.6366 14.0961L16.6493 8.4252C16.7252 8.09192 16.7252 7.74582 16.6493 7.41254C16.566 7.08205 16.4104 6.7742 16.1936 6.51128C15.9746 6.25 15.7017 6.03926 15.3936 5.89355C15.0762 5.7467 14.7306 5.67068 14.3809 5.67077H10.5328L11.0391 4.37457C11.2397 3.88784 11.3162 3.35894 11.2619 2.83533C11.1853 2.30894 10.9763 1.81065 10.6543 1.38723ZM4.75052 14.5518H3.029C2.91049 14.5525 2.79303 14.5296 2.68349 14.4844C2.57394 14.4392 2.47452 14.3726 2.39102 14.2885C2.23609 14.1199 2.14945 13.8997 2.14799 13.6708V8.02014C2.14913 7.901 2.17389 7.78328 2.22082 7.67377C2.26775 7.56427 2.33592 7.46515 2.4214 7.38216C2.50369 7.29576 2.60267 7.22698 2.71233 7.17998C2.822 7.13298 2.94007 7.10874 3.05938 7.10874H4.7809L4.75052 14.5518ZM10.6746 7.05811H14.3809C14.5145 7.05821 14.6462 7.08942 14.7657 7.14925C14.8875 7.20532 14.9948 7.28845 15.0796 7.39229C15.1675 7.49052 15.2301 7.60871 15.2619 7.73659C15.2922 7.8665 15.2922 8.00162 15.2619 8.13153L14.2493 13.8024C14.2087 14.017 14.094 14.2106 13.9252 14.3492C13.7619 14.4812 13.558 14.5528 13.348 14.5518H6.19862V6.45052L8.43659 1.38723H8.52773C8.9042 1.50037 9.23304 1.73413 9.4636 2.05252C9.69416 2.37092 9.81365 2.75627 9.80368 3.14925C9.8181 3.39741 9.78015 3.64583 9.69229 3.87836L9.23659 5.04292C9.15397 5.273 9.12623 5.51921 9.15558 5.76191C9.1877 6.00427 9.27425 6.23623 9.40875 6.44039C9.5535 6.6376 9.74028 6.80017 9.95558 6.91634C10.1774 7.03206 10.4244 7.0912 10.6746 7.08849V7.05811Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Facebook</button>
</div>
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="21" height="16" viewbox="0 0 21 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.22192 2.20503C2.36754 1.77115 2.78269 1.45455 3.26639 1.45455H17.9332C18.4169 1.45455 18.8321 1.77118 18.9777 2.2051L10.5999 8.02107L2.22192 2.20503ZM2.16639 3.94198V13.4545C2.16639 14.0529 2.66307 14.5455 3.26639 14.5455H17.9332C18.5365 14.5455 19.0332 14.0529 19.0332 13.4545V3.94206L11.0204 9.50462C10.7679 9.67991 10.4318 9.67991 10.1793 9.50462L2.16639 3.94198ZM20.4999 2.55809V13.4545C20.4999 14.8562 19.3465 16 17.9332 16H3.26639C1.85304 16 0.699707 14.8562 0.699707 13.4545V2.54545C0.699707 1.14379 1.85304 0 3.26639 0H17.9332C19.3407 0 20.4904 1.13441 20.4998 2.52818C20.5 2.53816 20.5001 2.54813 20.4999 2.55809Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Email</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="post-header">
<h1 class="post-title long unpublished">
No really, why can't we have raw UDP in JavaScript?
</h1>
<h3 class="subtitle">
In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS.
</h3>
<div class="post-subheader meta-subheader">
<div class="left">
<div class="facepile bylines-facepile">
<div class="facepile-faces">
<div class="profile-hover-wrapper">
<a href="https://substack.com/profile/11696674-casey-muratori?utm_source=author-byline-face" class="facepile-link"><img src="https://substackcdn.com/image/fetch/w_64,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3d02ef-2cd1-4704-89e6-7cd174389c6b_586x622.png" class="facepile-face first-face" /></a>
</div>
</div>
</div>
<div class="label-stack">
<div class="bylines">
<div class="profile-hover-wrapper">
<span class="byline-names"><a class="byline-profile-link" href="https://substack.com/profile/11696674-casey-muratori">Casey Muratori</a></span>
</div>
</div>
<div class="publish-context">
<time datetime="2022-07-05T02:58:16.304Z">Jul 5</time>
</div>
</div>
</div>
<div class="right">
<div class="post-ufi style-button themed">
<a role="button" class="post-ufi-button style-button has-label with-border"><svg role="img" style="height: 20px; width: 20px;" width="20" height="20" viewbox="0 0 24 24" fill="#000000" stroke-width="1.5" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="icon">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart">
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 0C1.46 6.7 1.33 10.28 4 13l8 8 8-8c2.67-2.72 2.54-6.3.42-8.42z"></path></svg>
</g></svg>
<div class="label">
12
</div></a><a role="button" href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp/comments" class="post-ufi-button style-button post-ufi-comment-button has-label with-border"><svg role="img" style="height: 20px; width: 20px;" width="20" height="20" viewbox="0 0 24 24" fill="#000000" stroke-width="1.5" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="icon">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle">
<path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"></path></svg>
</g></svg>
<div class="label">
18
</div></a><a role="button" href="javascript:void(0)" class="post-ufi-button style-button no-label with-border"><svg role="img" style="height: 20px; width: 20px;" width="20" height="20" viewbox="0 0 24 24" fill="#000000" stroke-width="1.5" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="icon">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-share">
<path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8"></path>
<polyline points="16 6 12 2 8 6"></polyline>
<line x1="12" y1="2" x2="12" y2="15"></line></svg>
</g></svg></a>
<div role="dialog" class="modal typography out gone share-dialog popup">
<div class="modal-table">
<div class="modal-row">
<div class="modal-cell modal-content no-fullscreen">
<div class="container">
<button data-testid="close-modal" class="button modal-btn modal-exit-btn no-margin" type="button" tabindex="0"><svg role="img" width="20" height="20" viewbox="0 0 20 20" fill="none" stroke-width="1" stroke="#666666" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M15 5L5 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 5L15 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</g></svg></button>
<div class="share-dialog-title">
Share this post
</div>
<div class="social-preview-box post">
<div class="social-image-box">
<img src="https://substackcdn.com/image/fetch/w_120,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg" />
</div>
<div class="social-labels">
<div class="social-title">
No really, why can't we have raw UDP in JavaScript?
</div>
<div class="social-subtitle">
www.computerenhance.com
</div>
</div>
</div>
<div class="share-action-row">
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="20" height="16" viewbox="0 0 20 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1303 0.000379039C10.9833 -0.00959082 9.87819 0.431464 9.05309 1.22855L9.04556 1.23593L7.79145 2.48303C7.50587 2.767 7.50453 3.22877 7.78844 3.51441C8.07235 3.80004 8.53401 3.80139 8.81959 3.51741L10.0698 2.27423C10.6194 1.74503 11.3546 1.45229 12.1177 1.45892C12.8824 1.46556 13.6139 1.77236 14.1546 2.31323C14.6954 2.8541 15.0021 3.58577 15.0087 4.35065C15.0154 5.11353 14.7229 5.84857 14.1943 6.39829L12.0116 8.58145L12.0115 8.58155C11.7159 8.87739 11.36 9.10617 10.9682 9.25237C10.5764 9.39857 10.1577 9.45878 9.74051 9.42889C9.32337 9.39901 8.91752 9.27975 8.55051 9.07918C8.1835 8.87862 7.8639 8.60146 7.6134 8.26649C7.3722 7.94396 6.91526 7.87807 6.5928 8.11933C6.27034 8.36059 6.20447 8.81763 6.44567 9.14016C6.82142 9.64261 7.30082 10.0584 7.85134 10.3592C8.40186 10.66 9.01062 10.8389 9.63634 10.8838C10.2621 10.9286 10.8901 10.8383 11.4779 10.619C12.0656 10.3997 12.5994 10.0565 13.0429 9.61274L15.2302 7.42494L15.2391 7.4159C16.036 6.59062 16.4769 5.48529 16.467 4.33797C16.457 3.19066 15.9969 2.09316 15.1858 1.28185C14.3746 0.470545 13.2774 0.0103489 12.1303 0.000379039ZM7.29806 5.11625C6.67234 5.07142 6.0443 5.16173 5.45654 5.38103C4.86882 5.60031 4.33502 5.94355 3.89153 6.38727L1.70423 8.57506L1.69534 8.5841C0.898438 9.40939 0.457483 10.5147 0.467451 11.662C0.477418 12.8094 0.937512 13.9069 1.74864 14.7182C2.55976 15.5295 3.65701 15.9897 4.80407 15.9996C5.95113 16.0096 7.05622 15.5685 7.88132 14.7715L7.89035 14.7626L9.13717 13.5155C9.42192 13.2307 9.42192 12.7689 9.13717 12.4841C8.85243 12.1993 8.39077 12.1993 8.10602 12.4841L6.86392 13.7265C6.31432 14.2552 5.57945 14.5477 4.81675 14.5411C4.05204 14.5344 3.32054 14.2276 2.77979 13.6868C2.23904 13.1459 1.93231 12.4142 1.92566 11.6494C1.91904 10.8865 2.21146 10.1514 2.74011 9.60172L4.92287 7.41846C5.21854 7.12262 5.57437 6.89384 5.96621 6.74763C6.35805 6.60143 6.77674 6.54123 7.19389 6.57111C7.61104 6.601 8.01688 6.72026 8.38389 6.92082C8.75091 7.12138 9.0705 7.39855 9.32101 7.73352C9.56221 8.05605 10.0191 8.12194 10.3416 7.88068C10.6641 7.63942 10.7299 7.18238 10.4887 6.85985C10.113 6.3574 9.63359 5.94165 9.08307 5.64081C8.53255 5.33997 7.92378 5.16107 7.29806 5.11625Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Copy link</button>
</div>
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="20" height="16" viewbox="0 0 20 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1524 0.286815C12.9848 -0.0318829 13.8948 -0.0864749 14.7592 0.130489C15.462 0.306912 16.107 0.655903 16.6376 1.14249C17.3169 0.89658 17.961 0.560161 18.5523 0.141743C18.7998 -0.0334198 19.1301 -0.0365939 19.381 0.133779C19.6318 0.304152 19.7507 0.612306 19.6791 0.907C19.4028 2.04538 18.8458 3.09393 18.0616 3.95753C18.0757 4.09811 18.083 4.23936 18.0835 4.3808L18.0835 4.38319C18.0835 9.29757 15.7264 12.8962 12.3452 14.7015C8.98147 16.4975 4.67843 16.4794 0.840591 14.3406C0.546545 14.1767 0.403384 13.8324 0.49452 13.5084C0.585656 13.1843 0.887269 12.9652 1.22363 12.9786C2.65157 13.0356 4.0647 12.7377 5.34034 12.12C4.06579 11.3575 3.15922 10.4438 2.53674 9.45782C1.73519 8.18825 1.43205 6.84263 1.37719 5.63204C1.32248 4.42456 1.51372 3.33632 1.71513 2.55507C1.81628 2.16276 1.92118 1.84328 2.00191 1.61926C2.04232 1.50714 2.0768 1.41859 2.10191 1.35643C2.11446 1.32534 2.12469 1.30081 2.13215 1.2832L2.14123 1.26201L2.14412 1.25538L2.14514 1.25307L2.14553 1.25217C2.1457 1.25179 2.14586 1.25144 2.81079 1.54604L2.14586 1.25144C2.25213 1.01158 2.47934 0.847546 2.74046 0.822176C3.00157 0.796805 3.25612 0.914031 3.40657 1.12894C4.15428 2.19698 5.15353 3.06271 6.31515 3.64923C7.26519 4.12892 8.2998 4.40971 9.35623 4.47759V4.41217C9.34536 3.52161 9.60685 2.64886 10.1058 1.91153C10.6058 1.17278 11.3201 0.605503 12.1524 0.286815ZM3.09343 3.03841C2.9284 3.71356 2.78659 4.6028 2.83025 5.5662C2.8764 6.58479 3.12882 7.67102 3.76666 8.68131C4.40153 9.68688 5.44569 10.6611 7.14733 11.4198C7.38821 11.5272 7.55207 11.7566 7.57557 12.0192C7.59906 12.2819 7.47851 12.5367 7.26052 12.6852C6.28428 13.3499 5.20629 13.8343 4.07717 14.1236C6.75502 14.8865 9.46059 14.5928 11.6602 13.4184C14.5413 11.8801 16.6285 8.79158 16.6289 4.38467C16.6283 4.20406 16.611 4.0239 16.5772 3.84652C16.5318 3.60859 16.6079 3.3637 16.7801 3.19336C17.0303 2.94581 17.2553 2.67591 17.4527 2.38779C17.1883 2.49441 16.9189 2.58923 16.6453 2.67187C16.3709 2.75477 16.0733 2.6687 15.8855 2.45208C15.4964 2.00326 14.9795 1.68547 14.4051 1.54127C13.8306 1.39708 13.2258 1.43333 12.6725 1.6452C12.1191 1.85707 11.6436 2.23446 11.3105 2.72674C10.9773 3.21904 10.8028 3.80236 10.8107 4.39779L10.8108 4.40751H10.8108V5.21813C10.8108 5.61242 10.4966 5.9349 10.1024 5.94515C8.56202 5.98522 7.03575 5.6425 5.65956 4.94765C4.69805 4.46217 3.83071 3.81535 3.09343 3.03841Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Twitter</button>
</div>
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="16" height="17" viewbox="0 0 16 17" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M10.6543 1.38723C10.3533 0.960814 9.95383 0.61341 9.48976 0.374567C9.02902 0.137956 8.51908 0.0130716 8.00115 0.0100098C7.86087 0.0101844 7.72354 0.0502687 7.60519 0.125581C7.48684 0.200893 7.39237 0.308324 7.3328 0.435326L5.00368 5.67077H3.029C2.72335 5.66964 2.42059 5.73003 2.13876 5.84833C1.85692 5.96663 1.60177 6.14043 1.38849 6.35938C1.16707 6.57502 0.991841 6.83346 0.873459 7.11897C0.755078 7.40447 0.696022 7.71108 0.699885 8.02014V13.691C0.699885 14.3087 0.945273 14.9012 1.38207 15.338C1.81886 15.7747 2.41128 16.0201 3.029 16.0201H13.348C13.8951 16.021 14.425 15.8283 14.8438 15.4762C15.2626 15.1241 15.5434 14.6352 15.6366 14.0961L16.6493 8.4252C16.7252 8.09192 16.7252 7.74582 16.6493 7.41254C16.566 7.08205 16.4104 6.7742 16.1936 6.51128C15.9746 6.25 15.7017 6.03926 15.3936 5.89355C15.0762 5.7467 14.7306 5.67068 14.3809 5.67077H10.5328L11.0391 4.37457C11.2397 3.88784 11.3162 3.35894 11.2619 2.83533C11.1853 2.30894 10.9763 1.81065 10.6543 1.38723ZM4.75052 14.5518H3.029C2.91049 14.5525 2.79303 14.5296 2.68349 14.4844C2.57394 14.4392 2.47452 14.3726 2.39102 14.2885C2.23609 14.1199 2.14945 13.8997 2.14799 13.6708V8.02014C2.14913 7.901 2.17389 7.78328 2.22082 7.67377C2.26775 7.56427 2.33592 7.46515 2.4214 7.38216C2.50369 7.29576 2.60267 7.22698 2.71233 7.17998C2.822 7.13298 2.94007 7.10874 3.05938 7.10874H4.7809L4.75052 14.5518ZM10.6746 7.05811H14.3809C14.5145 7.05821 14.6462 7.08942 14.7657 7.14925C14.8875 7.20532 14.9948 7.28845 15.0796 7.39229C15.1675 7.49052 15.2301 7.60871 15.2619 7.73659C15.2922 7.8665 15.2922 8.00162 15.2619 8.13153L14.2493 13.8024C14.2087 14.017 14.094 14.2106 13.9252 14.3492C13.7619 14.4812 13.558 14.5528 13.348 14.5518H6.19862V6.45052L8.43659 1.38723H8.52773C8.9042 1.50037 9.23304 1.73413 9.4636 2.05252C9.69416 2.37092 9.81365 2.75627 9.80368 3.14925C9.8181 3.39741 9.78015 3.64583 9.69229 3.87836L9.23659 5.04292C9.15397 5.273 9.12623 5.51921 9.15558 5.76191C9.1877 6.00427 9.27425 6.23623 9.40875 6.44039C9.5535 6.6376 9.74028 6.80017 9.95558 6.91634C10.1774 7.03206 10.4244 7.0912 10.6746 7.08849V7.05811Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Facebook</button>
</div>
<div class="action-icon">
<button class="button share-action" type="button" tabindex="0"><svg role="img" width="21" height="16" viewbox="0 0 21 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.22192 2.20503C2.36754 1.77115 2.78269 1.45455 3.26639 1.45455H17.9332C18.4169 1.45455 18.8321 1.77118 18.9777 2.2051L10.5999 8.02107L2.22192 2.20503ZM2.16639 3.94198V13.4545C2.16639 14.0529 2.66307 14.5455 3.26639 14.5455H17.9332C18.5365 14.5455 19.0332 14.0529 19.0332 13.4545V3.94206L11.0204 9.50462C10.7679 9.67991 10.4318 9.67991 10.1793 9.50462L2.16639 3.94198ZM20.4999 2.55809V13.4545C20.4999 14.8562 19.3465 16 17.9332 16H3.26639C1.85304 16 0.699707 14.8562 0.699707 13.4545V2.54545C0.699707 1.14379 1.85304 0 3.26639 0H17.9332C19.3407 0 20.4904 1.13441 20.4998 2.52818C20.5 2.53816 20.5001 2.54813 20.4999 2.55809Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button class="button share-action" type="button" tabindex="0">Email</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="visibility-check"></div>
<div class="">
<div class="available-content">
<div dir="auto" class="body markup">
<div class="captioned-image-container">
<figure>
<a class="image-link image2" target="_blank" rel="nofollow" href="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1456w" sizes="100vw" /><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg&quot;,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7578043,&quot;alt&quot;:&quot;A sculpture of a cartoon character stuck in a pipe.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false}" class="sizing-normal" alt="A sculpture of a cartoon character stuck in a pipe." title="A sculpture of a cartoon character stuck in a pipe." srcset="https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1456w" sizes="100vw" /></picture></a>
</figure>
</div>
<p>
<span>By now I</span> <a href="https://twitter.com/cmuratori/status/1543874684868931584" rel="">should know better</a> <span>than to ask on Twitter for a “rigorous analysis” of anything. As George W. Bush said, “Fool me once, shame on you…</span> <a href="https://www.youtube.com/watch?v=ntwdH3Q54ZY" rel="">fool me cant fooled again</a><span>.”</span>
</p>
<p>
I dont want to be “fool me cant get fooled again”, so I officially give up on technical tweets. Todays the last day I will ever post anything technical on Twitter, I promise. Instead, you will be forced to endure yet another Substack, so I can post 3,000-word posts that no one will read.
</p>
<p>
Here we go:
</p>
<h2 class="header-with-anchor-widget">
Why have a browser raw UDP API?
</h2>
<div id="§why-have-a-browser-raw-udp-api" class="header-anchor-widget">
<div class="header-anchor-widget-button-container">
<h2 class="header-with-anchor-widget">
<a class="header-anchor-widget-button" href="https://www.computerenhance.com/i/62549671/why-have-a-browser-raw-udp-api"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="header-anchor-widget-icon">
<path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"></path>
<path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"></path></svg></a>
</h2>
</div>
</div>
<p>
The goal with raw UDP is very simple: better performance and security on the server side.
</p>
<p>
<span>HTTPS is an unbaked sausage made by grinding pure text HTTP with TLS and encasing the result in an arbitrary selection of third-party animal intestine… err, I mean, “highly secure” certificates provided by arbitrarily selected certificate providers. Implementing HTTPS is a massive amount of code that is inexorably slow. It is not only theoretically difficult to secure completely, but is</span> <a href="https://www.openssl.org/news/vulnerabilities.html" rel="">insecure in practice</a> <span>in popular implementations available to the public.</span>
</p>
<p>
<span>Oh, and the certificate authorities are also insecure, by the way - but thats</span> <a href="https://en.wikipedia.org/wiki/DigiNotar" rel="">another story</a> <span>(and</span> <a href="https://decoded.avast.io/luigicamastra/backdoored-client-from-mongolian-ca-monpass/" rel="">another</a><span>, and</span> <a href="https://www.computerworld.com/article/2507090/firm-points-finger-at-iran-for-ssl-certificate-theft.html" rel="">another</a><span>, and</span> <a href="https://sslmate.com/resources/certificate_authority_failures" rel=""></a><span>)</span>
</p>
<p>
It also relied (up until recently) on TCP, which, unless you plan to write a completely custom network stack for every type of server/NIC you ever use, requires the underlying kernel to understand and track network connections. This means that you inherit substantial overhead, and perhaps vulnerabilities as well, from the TCP/IP substrate before you even begin to write your server code.
</p>
<p>
If you were a large company with significant academic and engineering resources, you might instead want to design your own private secure protocol that:
</p>
<ol>
<li>
<p>
Uses encryption you control, so it cannot be bypassed by hacking the certificate authority,
</p>
</li>
<li>
<p>
Uses UDP to avoid having OS connection state on the server side, and
</p>
</li>
<li>
<p>
Uses a well-designed, known packet structure to improve throughput and reduce security vulnerabilities from HTTP/TLS parsing.
</p>
</li>
</ol>
<p>
<span>The first thing on that list is half-possible now. Although theres nothing you can (ever</span><a class="footnote-anchor" id="footnote-anchor-1" href="#footnote-1" rel="">1</a><span>) do to avoid man-in-the-middle attacks the very first time someone interacts with your server, web APIs have long made it possible to store data on the client for later use. One use for that data would be storing your own set of public keys.</span>
</p>
<p>
<span>So even using nothing newer than XHR and cookies, you could theoretically add your own layer of encryption to anything you send to the server. This would ensure that any subsequent hack of the certificate authority could not inspect or modify your packets. Itd be much less efficient than rolling your own top-to-bottom, because now you pay the entire cost for your encryption</span> <em>and</em> <span>TLS. But you</span> <em>can</em> <span>do it.</span>
</p>
<p>
<span>Its slow, but possible. Call it</span> <em>half-possible</em><span>, like I did above.</span>
</p>
<p>
<span>The second thing on the list is sort-of possible now as well. If you can somehow manage to use</span> <a href="https://en.wikipedia.org/wiki/HTTP/3" rel="">HTTP/3</a> <span>exclusively as your target platform, you will still be talking HTTP but youll be doing it over UDP instead of TCP, and can manage connection state however you wish without OS intervention.</span>
</p>
<p>
<span>It is probably unrealistic to assume that you could do this in practice today. If you didnt care about broad compatibility, you probably wouldnt be deploying on the web anyway, so presumably the current adoption of HTTP/3 is insufficient. But at least it</span> <em>exists</em><span>, and perhaps if adoption continues to grow,</span> <em>eventually</em> <span>it will be possible to require HTTP/3 without losing a significant number of users. For now, its only something you can do on the side - you still have to have a traditional HTTPS fallback.</span>
</p>
<p>
<span>Which brings us to the third item on the list, and the real sticking point. As far as Im aware, no current or planned future Web API ever lets you do number three. There are many new web “technologies” swarming around the custom packet idea (</span><a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API" rel="">WebRTC</a><span>,</span> <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" rel="">WebSockets</a><span>,</span> <a href="https://github.com/w3c/webtransport" rel="">WebTransport</a><span>), but to the best of my knowledge, all of them require an HTTPS connection to be made first, so your “custom packet” servers still need to implement all of HTTPS anyway.</span>
</p>
<h2 class="header-with-anchor-widget">
What is the deployment scenario?
</h2>
<div id="§what-is-the-deployment-scenario" class="header-anchor-widget">
<div class="header-anchor-widget-button-container">
<h2 class="header-with-anchor-widget">
<a class="header-anchor-widget-button" href="https://www.computerenhance.com/i/62549671/what-is-the-deployment-scenario"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="header-anchor-widget-icon">
<path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"></path>
<path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"></path></svg></a>
</h2>
</div>
</div>
<p>
I can imagine someone raising the following objection at this point: “If you dont support HTTPS on the server, how do you serve the WASM/JavaScript/whatever with the custom packet logic in the first place?”
</p>
<p>
Thats a reasonable question.
</p>
<p>
The answer is, the two most logical deployment scenarios I can think of both involve a separate server (or process) for the initial HTTPS transaction.
</p>
<p>
The first is what I imagine would be the most common: you upload to a CDN a traditional web package containing the PWA-style web worker necessary to do your own custom packet logic. The CDN serves this (static) content everywhere for you. They obviously implement HTTPS already, because thats what they do for a living, and theyre not your servers anyway so you dont care.
</p>
<p>
<span>The second would be less common, but plausible: you run your own CDN-equivalent, because</span> <a href="https://knowyourmeme.com/memes/chuck-norris-facts" rel="">youre just that hard core</a><span>. But you expect that your HTTPS code is more vulnerable than your custom code, since HTTPS is vastly more complicated and has ridiculous things in it like arbitrary text parsing, which no one in their right mind would ever put into a “secure” protocol. So you cabin your HTTPS server instances into their own restricted processes or own machines entirely. This prevents exploits of the HTTPS code from affecting anything other than newly connecting users - existing users (who are only talking to your custom servers) remain unharmed.</span>
</p>
<p>
In neither scenario do you actually include HTTPS code in any of the processes running your actual secure server.
</p>
<h2 class="header-with-anchor-widget">
What precedent has been set by other “secure” APIs in the browser?
</h2>
<div id="§what-precedent-has-been-set-by-other-secure-apis-in-the-browser" class="header-anchor-widget">
<div class="header-anchor-widget-button-container">
<h2 class="header-with-anchor-widget">
<a class="header-anchor-widget-button" href="https://www.computerenhance.com/i/62549671/what-precedent-has-been-set-by-other-secure-apis-in-the-browser"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="header-anchor-widget-icon">
<path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"></path>
<path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"></path></svg></a>
</h2>
</div>
</div>
<p>
So thats the hopefully-at-least-somewhat-convincing explanation of why someone might want raw UDP. Now the question is, can raw UDP be provided by a browser in a way that is “secure”?
</p>
<p>
<span>Im putting a lot of these words in scare quotes because browsers</span> <em>arent</em> <span>secure for any serious definition of that word, and hopefully that is overwhelmingly obvious to everyone who has ever used one. But just to be clear about the landscape, there are two different ways browsers are not secure:</span>
</p>
<ol>
<li>
<p>
<span>The web as a platform consists of massive, overlapping, poorly-specified APIs that require millions of lines of code to fully implement. As a result, browsers inexorably have</span> <a href="https://www.mozilla.org/en-US/security/known-vulnerabilities/firefox/" rel="">an effectively infinite number of security exploits</a> <span>waiting to be found.</span>
</p>
</li>
<li>
<p>
Browsers include the ability, sans exploit, to transmit information from the client computer to any number of remote servers. Without the ability to control this behavior, the users data could be misappropriated.
</p>
</li>
</ol>
<p>
Clearly, for raw UDP, we only care about the second one of these. The first one happens in browsers all the time already and theres no reason to suspect that raw UDP would somehow have more implementation code vulnerabilities on average than any other part of the sprawling browser substrate.
</p>
<p>
<span>So the question is, assuming the browser</span> <em>has not</em> <span>been exploited, what is the security standard for web features, and can raw UDP be implemented under that standard or not?</span>
</p>
<p>
As a point of comparison, I will use the example of the current camera/microphone/location policy as it presently exists. That will be our “gold standard”, since if it were not considered “secure” by web implementers, presumably it would not have been knowingly shipped in web browsers everywhere for the past several years.
</p>
<p>
As everyone who uses a web browser knows, a web site at present is allowed to ask you for permission, temporarily or permanently (your choice), to access your camera, microphone, and location data. Once you say “yes” to any one of these things, that site can transmit that data anywhere in the world, and use it for any purpose, trivially.
</p>
<p>
Allow me to provide a worked example.
</p>
<p>
<span>Suppose I partner with Jeffrey Toobin to make a cybersex conduit site for people who, like him, see the value in quickly switching tabs away from your work meetings to get down to some</span> <em>real</em> <span>business. We launch cyberballsdeep.net, and its a big success.</span>
</p>
<p>
When a user visits our site, they see at most two security-related things:
</p>
<ol>
<li>
<p>
An allow/deny request for access to the microphone and camera, and
</p>
</li>
<li>
<p>
A lock icon indicating that the connection has been signed by a third party warranting that this connection is end-to-end encrypted from the users machine to some server somewhere with the secure keys for cyberballsdeep.net.
</p>
</li>
</ol>
<p>
Assuming you click “allow” - which you have to in order to use the service - the servers at cyberballsdeep.net can now do anything they want with your (very sensitive) video data. They can, for example, record you while you are toobin and play it back at any time, anywhere, at their discretion. They could play it on a billboard in Times Square, they could send it to your spouse - anything goes.
</p>
<p>
So the “security standard” that you are getting, in practice, exactly mirrors the two things you saw:
</p>
<ol>
<li>
<p>
You know your sensitive data will not be captured unless you click “allow”, and
</p>
</li>
<li>
<p>
You know that nobody will be able to see your sensitive data unless either cyberballsdeep.net or the issuing certificate authority let them (either intentionally, or unintentionally if theyve been hacked).
</p>
</li>
</ol>
<p>
<span>Thats it. You dont know anything else. In practice, you basically have no security guarantees other than a warrant that your sensitive data will go to a particular named party</span> <em>first</em> <span>before it goes somewhere else.</span>
</p>
<p>
<span>Hopefully we can all agree that this extremely low bar for security is the only hurdle one should have to clear in order to dismiss concerns of “security” as a reason not to implement a feature in a W3C spec. Its not much, but it is</span> <em>something</em><span>.</span>
</p>
<h2 class="header-with-anchor-widget">
Can raw UDP meet this security standard?
</h2>
<div id="§can-raw-udp-meet-this-security-standard" class="header-anchor-widget">
<div class="header-anchor-widget-button-container">
<h2 class="header-with-anchor-widget">
<a class="header-anchor-widget-button" href="https://www.computerenhance.com/i/62549671/can-raw-udp-meet-this-security-standard"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="header-anchor-widget-icon">
<path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"></path>
<path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"></path></svg></a>
</h2>
</div>
</div>
<p>
<span>OK, finally, with all that out of the way, this is what I actually wanted someone to point me to</span> <a href="https://twitter.com/cmuratori/status/1543874684868931584" rel="">when I asked about this on Twitter</a><span>. I just wanted to see that someone, somewhere, had worked out exactly why UDP could not be made to fit the same security model considered acceptable across other basic web features already deployed and considered “secure”.</span>
</p>
<p>
Since nobody sent me such a thing, I am still stuck with my own security modeling, with nothing to compare against. My model goes something like this:
</p>
<p>
Step one - the “allow/deny” step - is easy for raw UDP to provide. The browser is still sitting between the JavaScript/WASM layer and the OS sockets layer, so it can ensure that inbound and outbound packets are filtered any way the browser wishes.
</p>
<p>
This means that it would be trivial for a browser to only allow UDP packets to and from servers that the user has authorized, as it does with microphone, camera, and location data. Any site that wishes to access raw UDP simply provides a hostname to the browser, and the browser asks the user whether they wish to allow the page to communicate with that site.
</p>
<p>
Furthermore, since the browser already allows the page to send as much HTTPS data as it wants back to the originating site, one could optionally allow any site to send UDP packets back to its own (exact) originating IP without asking the user. This is not necessary for raw UDP to work, but I cant think of any violation of “step one” that would happen as a result, so it could be considered.
</p>
<p>
<span>Note that this is</span> <em>not</em> <span>true for something like camera/microphone/location data. Those are additional data sources to which the page gets access, so if anything, raw UDP permission is</span> <em>less</em> <span>dangerous in terms of user permission, since at no time does the page itself get additional access to the users data, regardless of whether they allow UDP communication.</span>
</p>
<p>
Which brings us to step two.
</p>
<p>
As far as I can tell, theres actually nothing special about step two. The original web page was served by HTTPS, obviously, since thats the only way the browser supports getting WASM/JavaScript downloaded in the first place. So the originating server and code are already exactly as “secure” as they would be in any other scenario.
</p>
<p>
The user had to affirmatively allow the destination name, so the page can only send UDP to a specifically approved endpoint.
</p>
<p>
<span>So the only question is,</span> <em>can the user be sure that the data sent to that endpoint is encrypted such that only the endpoint or the certificate authority can decrypt it?</em>
</p>
<p>
<span>I cant know the hivemind of a W3C committee (thank the heavens). But if I had to guess, I would suspect that this is why they didnt want to allow raw UDP (or raw TCP for that matter). In their mind, it probably seems</span> <em>less secure</em> <span>than HTTPS to allow a web page to implement its own secure UDP protocol.</span>
</p>
<p>
<span>However, to my mind, this is based upon a flawed assumption. That assumption is that somehow web implementers</span> <em>can</em> <span>be trusted to deploy their encryption keys securely, but</span> <em>cannot</em> <span>be trusted to deploy their protocol securely.</span>
</p>
<p>
To be more specific, HTTPS can be intercepted trivially if the attacker A) has a machine on the route between the endpoints and B) has access to the servers keys, or any certificate authoritys signing capability. (A) either happens or it doesnt - theres no way to control it - so (B) is really the entire question.
</p>
<p>
So the notion that allowing web pages to use UDP for transmission is less secure than HTTPS seems to me to be predicated on the notion that web developers can be trusted to do something complicated in one place (run a set of servers without leaking keys), but also cannot be trusted to do something complicated in another (download, for example, a JavaScript UDP encryption library and use it).
</p>
<p>
Stated alternately, the hard constraint on the client side that you cant roll your packet code “for security reasons” is nowhere to be found on the server side. There is no requirement anywhere in W3C or anywhere else that says your web server has to be… well… anything at all, really. You can just go ahead and write your own code from top to bottom. You can even have a dedicated web page on your site that has the entire cryptographic key set for the server posted on it for people to cut-and-paste, so everyone can impersonate your server to anyone, anywhere, at any time. You can leave a thumb drive with your keys at the bar. You can generate your keys with a random seed of 0x000000000000000000. Anything goes.
</p>
<p>
<span>Nobody seems to be panicked about this. Nobody has pushed the policy that the W3C should standardize on a specific web server deployment that you are forced to use, or a set of n of them made by Google/Mozilla/Apple, or what have you. It is just assumed that everyone is allowed to write their own</span> <em>server</em> <span>packet handling, but that no one is allowed to write their own</span> <em>client</em> <span>packet handling.</span>
</p>
<p>
So thats what I would like explained. Internet, justify this!
</p>
<h2 class="header-with-anchor-widget">
Appendix A.1.2b subsection 12: What about destination consent?
</h2>
<div id="§appendix-a12b-subsection-12-what-about-destination-consent" class="header-anchor-widget">
<div class="header-anchor-widget-button-container">
<h2 class="header-with-anchor-widget">
<a class="header-anchor-widget-button" href="https://www.computerenhance.com/i/62549671/appendix-a12b-subsection-12-what-about-destination-consent"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="header-anchor-widget-icon">
<path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"></path>
<path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"></path></svg></a>
</h2>
</div>
</div>
<p>
I have seen people mention (but not support) a claim that raw UDP would cause “denial of service” problems because malicious web pages would send UDP packets to random servers in an attempt to overload them. This claim seems completely baseless to me, because there is no reason why you cant employ the relevant XHR DDoS restrictions to UDP. If DDoS was the concern, just require that UDP packets be sent exclusively within the same domain as the originating code.
</p>
<p>
<span>Furthermore, you could restrict the port ranges of raw web UDP to some assigned range. A new port range could be explicitly reserved</span> <em>just for raw web UDP</em> <span>if that makes people more comfortable, so it could literally be discarded at the gateway on any network that doesnt want to support raw UDP for web, making it easier to deal with than UDP attacks from native code and viruses which can choose their ports at will.</span>
</p>
<p>
<span>At that point, I fail to see how raw UDP from the browser could be significantly more dangerous than XHR, unless I am missing some particularly clever use of UDP. And again,</span> <em>thats why I asked for writeups in my original tweet</em><span>. Im totally willing to believe Im missing something, but I want to see a complete technical explanation about what it is.</span>
</p>
<p>
<span>Now, none of this is the same as saying I cant see how you would perform DDoS attacks with raw UDP. I certainly can. I just cant see how you would perform them</span> <em>more easily than with XHR,</em> <span>which obviously is considered “secure”</span><em>.</em>
</p>
<p>
As a simple example, suppose a commercial CDN distributes the payload of ddosfuntimes.com. On the main page, theres an XHR to target.ddosfuntimes.com. Even though the CDN is a completely different set of IP addresses as target.ddosfuntimes.com, this is completely legal under XHR policy.
</p>
<p>
The owners of ddosfuntimes.com can go ahead and set the IP address in their DNS records to point target.ddosfuntimes.com at any server they want, and they will receive all the XHR traffic from every browser that visits the page. And to the best of my knowledge, there isnt a damn thing the target can do about that.
</p>
<p>
So unless Im missing something, XHR already allows you to target any website you wish with unwanted traffic from anyone who visits your site. So why the concern about UDP?
</p>
<div class="footnote" id="footnote-1">
<a href="#footnote-anchor-1" class="footnote-number" contenteditable="false" rel="">1</a>
<div class="footnote-content">
<p>
<span>This is way off topic, but in case it struck people as odd: all secure systems have a root trust problem. At some point you have to get</span> <em>something</em> <span>from</span> <em>somebody</em> <span>that you will just blindly trust. This is the root of the chain of trust, and unfortunately, theres really nothing you can do to make it secure. You just have to hope that this initial exchange is trusted.</span>
</p>
<p>
So in the case of web browsers, you have to keep in mind that HTTPS doesnt actually guarantee you anything beyond a chain of trust. You are implicitly trusting that a) nobody messed with the browser when you downloaded it, b) none of the certificate authorities trusted by that browser download have been compromised, c) the certificate for signing browser root certificate updates hasnt itself been compromised.
</p>
<p>
Etc., etc.
</p>
<p>
<span>So in general, when we talk about adding security to a protocol, we can only talk about securing it</span> <em>up to a point</em><span>. No matter what we do, there will never be a way for it to be</span> <em>completely</em> <span>secure, because the chain of trust is not infinite, and any of its endpoints (in this case, the browser itself or any certificate authority) can lie to you for as long as it takes for a security firm to catch them doing it.</span>
</p>
</div>
</div>
</div>
</div>
<div class="visibility-check"></div>
<div class="post-end-cta-full">
<div class="visibility-check"></div>
<h3>
Subscribe to <b>Computer, Enhance!</b>
</h3>
<p class="end-cta-author-subs">
By Casey Muratori&#160;&#160;·&#160;&#160;Launched a day ago
</p>
<p class="end-cta-hero-text">
Technology, systems, interviews, commentary.
</p>
<div class="subscribe-widget">
<form class="form" action="/api/v1/free?nojs=true" method="post" novalidate="">
<input type="hidden" name="first_url" value="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp" /><input type="hidden" name="first_referrer" /><input type="hidden" name="current_url" value="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp" /><input type="hidden" name="current_referrer" /><input type="hidden" name="referral_code" /><input type="hidden" name="source" value="post-end-cta" />
<div class="sideBySideWrap">
<input type="email" name="email" placeholder="Type your email…" /><button tabindex="0" class="button rightButton primary subscribe-btn" type="submit"><b class="button-text">Subscribe</b></button>
</div>
<div id="error-container"></div>
<div class="subtle-help-text below-input"></div>
</form>
</div>
</div>
<div class="post-footer use-separators">
<div class="facepile">
<div class="facepile-faces">
<div class="profile-hover-wrapper">
<a class="facepile-link" href="https://substack.com/profile/12223673-sir-pinecone?utm_source=post-reactions-face"><img class="facepile-face" src="https://substackcdn.com/image/fetch/w_64,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9b69a425-b791-4e1e-9bc6-27d118d6f6f7_320x292.png" /></a>
</div>
<div class="profile-hover-wrapper">
<a class="facepile-link" href="https://substack.com/profile/43048124-tanner-davies?utm_source=post-reactions-face"><img class="facepile-face" src="https://substackcdn.com/image/fetch/w_64,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F8982a604-b3e4-466b-b184-2069a70ba11e_96x96.jpeg" /></a>
</div>
<div class="profile-hover-wrapper">
<a class="facepile-link" href="https://substack.com/profile/93579482-kaan?utm_source=post-reactions-face"><img class="facepile-face" src="https://substackcdn.com/image/fetch/w_64,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6467f9cf-ef84-4b71-a0af-104fb27aa81b_144x144.png" /></a>
</div>
<div class="profile-hover-wrapper">
<a class="facepile-link" href="https://substack.com/profile/4664846-shakthi-visagan?utm_source=post-reactions-face"><img class="facepile-face first-face" src="https://substackcdn.com/image/fetch/w_64,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F8975a127-32c0-4d5d-923b-f2ae82cfb031_400x400.jpeg" /></a>
</div>
</div>
<div class="facepile-quantity has-reactors">
12 likes
</div>
</div>
<div class="post-ufi style-button themed">
<a role="button" class="post-ufi-button style-button has-label with-border"><svg role="img" width="20" height="20" viewbox="0 0 24 24" fill="#000000" stroke-width="1.5" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="icon" style="height: 20px; width: 20px;">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart">
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 0C1.46 6.7 1.33 10.28 4 13l8 8 8-8c2.67-2.72 2.54-6.3.42-8.42z"></path></svg>
</g></svg>
<div class="label">
12
</div></a><a role="button" class="post-ufi-button style-button post-ufi-comment-button has-label with-border" href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp/comments"><svg role="img" width="20" height="20" viewbox="0 0 24 24" fill="#000000" stroke-width="1.5" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="icon" style="height: 20px; width: 20px;">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle">
<path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"></path></svg>
</g></svg>
<div class="label">
18
</div></a><a role="button" class="post-ufi-button style-button no-label with-border" href="javascript:void(0)"><svg role="img" width="20" height="20" viewbox="0 0 24 24" fill="#000000" stroke-width="1.5" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="icon" style="height: 20px; width: 20px;">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-share">
<path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8"></path>
<polyline points="16 6 12 2 8 6"></polyline>
<line x1="12" y1="2" x2="12" y2="15"></line></svg>
</g></svg></a>
<div class="modal typography out gone share-dialog popup" role="dialog">
<div class="modal-table">
<div class="modal-row">
<div class="modal-cell modal-content no-fullscreen">
<div class="container">
<button tabindex="0" data-testid="close-modal" class="button modal-btn modal-exit-btn no-margin" type="button"><svg role="img" width="20" height="20" viewbox="0 0 20 20" fill="none" stroke-width="1" stroke="#666666" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M15 5L5 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 5L15 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</g></svg></button>
<div class="share-dialog-title">
Share this post
</div>
<div class="social-preview-box post">
<div class="social-image-box">
<img src="https://substackcdn.com/image/fetch/w_120,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg" />
</div>
<div class="social-labels">
<div class="social-title">
No really, why can't we have raw UDP in JavaScript?
</div>
<div class="social-subtitle">
www.computerenhance.com
</div>
</div>
</div>
<div class="share-action-row">
<div class="action-icon">
<button tabindex="0" class="button share-action" type="button"><svg role="img" width="20" height="16" viewbox="0 0 20 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1303 0.000379039C10.9833 -0.00959082 9.87819 0.431464 9.05309 1.22855L9.04556 1.23593L7.79145 2.48303C7.50587 2.767 7.50453 3.22877 7.78844 3.51441C8.07235 3.80004 8.53401 3.80139 8.81959 3.51741L10.0698 2.27423C10.6194 1.74503 11.3546 1.45229 12.1177 1.45892C12.8824 1.46556 13.6139 1.77236 14.1546 2.31323C14.6954 2.8541 15.0021 3.58577 15.0087 4.35065C15.0154 5.11353 14.7229 5.84857 14.1943 6.39829L12.0116 8.58145L12.0115 8.58155C11.7159 8.87739 11.36 9.10617 10.9682 9.25237C10.5764 9.39857 10.1577 9.45878 9.74051 9.42889C9.32337 9.39901 8.91752 9.27975 8.55051 9.07918C8.1835 8.87862 7.8639 8.60146 7.6134 8.26649C7.3722 7.94396 6.91526 7.87807 6.5928 8.11933C6.27034 8.36059 6.20447 8.81763 6.44567 9.14016C6.82142 9.64261 7.30082 10.0584 7.85134 10.3592C8.40186 10.66 9.01062 10.8389 9.63634 10.8838C10.2621 10.9286 10.8901 10.8383 11.4779 10.619C12.0656 10.3997 12.5994 10.0565 13.0429 9.61274L15.2302 7.42494L15.2391 7.4159C16.036 6.59062 16.4769 5.48529 16.467 4.33797C16.457 3.19066 15.9969 2.09316 15.1858 1.28185C14.3746 0.470545 13.2774 0.0103489 12.1303 0.000379039ZM7.29806 5.11625C6.67234 5.07142 6.0443 5.16173 5.45654 5.38103C4.86882 5.60031 4.33502 5.94355 3.89153 6.38727L1.70423 8.57506L1.69534 8.5841C0.898438 9.40939 0.457483 10.5147 0.467451 11.662C0.477418 12.8094 0.937512 13.9069 1.74864 14.7182C2.55976 15.5295 3.65701 15.9897 4.80407 15.9996C5.95113 16.0096 7.05622 15.5685 7.88132 14.7715L7.89035 14.7626L9.13717 13.5155C9.42192 13.2307 9.42192 12.7689 9.13717 12.4841C8.85243 12.1993 8.39077 12.1993 8.10602 12.4841L6.86392 13.7265C6.31432 14.2552 5.57945 14.5477 4.81675 14.5411C4.05204 14.5344 3.32054 14.2276 2.77979 13.6868C2.23904 13.1459 1.93231 12.4142 1.92566 11.6494C1.91904 10.8865 2.21146 10.1514 2.74011 9.60172L4.92287 7.41846C5.21854 7.12262 5.57437 6.89384 5.96621 6.74763C6.35805 6.60143 6.77674 6.54123 7.19389 6.57111C7.61104 6.601 8.01688 6.72026 8.38389 6.92082C8.75091 7.12138 9.0705 7.39855 9.32101 7.73352C9.56221 8.05605 10.0191 8.12194 10.3416 7.88068C10.6641 7.63942 10.7299 7.18238 10.4887 6.85985C10.113 6.3574 9.63359 5.94165 9.08307 5.64081C8.53255 5.33997 7.92378 5.16107 7.29806 5.11625Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button tabindex="0" class="button share-action" type="button">Copy link</button>
</div>
<div class="action-icon">
<button tabindex="0" class="button share-action" type="button"><svg role="img" width="20" height="16" viewbox="0 0 20 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.1524 0.286815C12.9848 -0.0318829 13.8948 -0.0864749 14.7592 0.130489C15.462 0.306912 16.107 0.655903 16.6376 1.14249C17.3169 0.89658 17.961 0.560161 18.5523 0.141743C18.7998 -0.0334198 19.1301 -0.0365939 19.381 0.133779C19.6318 0.304152 19.7507 0.612306 19.6791 0.907C19.4028 2.04538 18.8458 3.09393 18.0616 3.95753C18.0757 4.09811 18.083 4.23936 18.0835 4.3808L18.0835 4.38319C18.0835 9.29757 15.7264 12.8962 12.3452 14.7015C8.98147 16.4975 4.67843 16.4794 0.840591 14.3406C0.546545 14.1767 0.403384 13.8324 0.49452 13.5084C0.585656 13.1843 0.887269 12.9652 1.22363 12.9786C2.65157 13.0356 4.0647 12.7377 5.34034 12.12C4.06579 11.3575 3.15922 10.4438 2.53674 9.45782C1.73519 8.18825 1.43205 6.84263 1.37719 5.63204C1.32248 4.42456 1.51372 3.33632 1.71513 2.55507C1.81628 2.16276 1.92118 1.84328 2.00191 1.61926C2.04232 1.50714 2.0768 1.41859 2.10191 1.35643C2.11446 1.32534 2.12469 1.30081 2.13215 1.2832L2.14123 1.26201L2.14412 1.25538L2.14514 1.25307L2.14553 1.25217C2.1457 1.25179 2.14586 1.25144 2.81079 1.54604L2.14586 1.25144C2.25213 1.01158 2.47934 0.847546 2.74046 0.822176C3.00157 0.796805 3.25612 0.914031 3.40657 1.12894C4.15428 2.19698 5.15353 3.06271 6.31515 3.64923C7.26519 4.12892 8.2998 4.40971 9.35623 4.47759V4.41217C9.34536 3.52161 9.60685 2.64886 10.1058 1.91153C10.6058 1.17278 11.3201 0.605503 12.1524 0.286815ZM3.09343 3.03841C2.9284 3.71356 2.78659 4.6028 2.83025 5.5662C2.8764 6.58479 3.12882 7.67102 3.76666 8.68131C4.40153 9.68688 5.44569 10.6611 7.14733 11.4198C7.38821 11.5272 7.55207 11.7566 7.57557 12.0192C7.59906 12.2819 7.47851 12.5367 7.26052 12.6852C6.28428 13.3499 5.20629 13.8343 4.07717 14.1236C6.75502 14.8865 9.46059 14.5928 11.6602 13.4184C14.5413 11.8801 16.6285 8.79158 16.6289 4.38467C16.6283 4.20406 16.611 4.0239 16.5772 3.84652C16.5318 3.60859 16.6079 3.3637 16.7801 3.19336C17.0303 2.94581 17.2553 2.67591 17.4527 2.38779C17.1883 2.49441 16.9189 2.58923 16.6453 2.67187C16.3709 2.75477 16.0733 2.6687 15.8855 2.45208C15.4964 2.00326 14.9795 1.68547 14.4051 1.54127C13.8306 1.39708 13.2258 1.43333 12.6725 1.6452C12.1191 1.85707 11.6436 2.23446 11.3105 2.72674C10.9773 3.21904 10.8028 3.80236 10.8107 4.39779L10.8108 4.40751H10.8108V5.21813C10.8108 5.61242 10.4966 5.9349 10.1024 5.94515C8.56202 5.98522 7.03575 5.6425 5.65956 4.94765C4.69805 4.46217 3.83071 3.81535 3.09343 3.03841Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button tabindex="0" class="button share-action" type="button">Twitter</button>
</div>
<div class="action-icon">
<button tabindex="0" class="button share-action" type="button"><svg role="img" width="16" height="17" viewbox="0 0 16 17" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M10.6543 1.38723C10.3533 0.960814 9.95383 0.61341 9.48976 0.374567C9.02902 0.137956 8.51908 0.0130716 8.00115 0.0100098C7.86087 0.0101844 7.72354 0.0502687 7.60519 0.125581C7.48684 0.200893 7.39237 0.308324 7.3328 0.435326L5.00368 5.67077H3.029C2.72335 5.66964 2.42059 5.73003 2.13876 5.84833C1.85692 5.96663 1.60177 6.14043 1.38849 6.35938C1.16707 6.57502 0.991841 6.83346 0.873459 7.11897C0.755078 7.40447 0.696022 7.71108 0.699885 8.02014V13.691C0.699885 14.3087 0.945273 14.9012 1.38207 15.338C1.81886 15.7747 2.41128 16.0201 3.029 16.0201H13.348C13.8951 16.021 14.425 15.8283 14.8438 15.4762C15.2626 15.1241 15.5434 14.6352 15.6366 14.0961L16.6493 8.4252C16.7252 8.09192 16.7252 7.74582 16.6493 7.41254C16.566 7.08205 16.4104 6.7742 16.1936 6.51128C15.9746 6.25 15.7017 6.03926 15.3936 5.89355C15.0762 5.7467 14.7306 5.67068 14.3809 5.67077H10.5328L11.0391 4.37457C11.2397 3.88784 11.3162 3.35894 11.2619 2.83533C11.1853 2.30894 10.9763 1.81065 10.6543 1.38723ZM4.75052 14.5518H3.029C2.91049 14.5525 2.79303 14.5296 2.68349 14.4844C2.57394 14.4392 2.47452 14.3726 2.39102 14.2885C2.23609 14.1199 2.14945 13.8997 2.14799 13.6708V8.02014C2.14913 7.901 2.17389 7.78328 2.22082 7.67377C2.26775 7.56427 2.33592 7.46515 2.4214 7.38216C2.50369 7.29576 2.60267 7.22698 2.71233 7.17998C2.822 7.13298 2.94007 7.10874 3.05938 7.10874H4.7809L4.75052 14.5518ZM10.6746 7.05811H14.3809C14.5145 7.05821 14.6462 7.08942 14.7657 7.14925C14.8875 7.20532 14.9948 7.28845 15.0796 7.39229C15.1675 7.49052 15.2301 7.60871 15.2619 7.73659C15.2922 7.8665 15.2922 8.00162 15.2619 8.13153L14.2493 13.8024C14.2087 14.017 14.094 14.2106 13.9252 14.3492C13.7619 14.4812 13.558 14.5528 13.348 14.5518H6.19862V6.45052L8.43659 1.38723H8.52773C8.9042 1.50037 9.23304 1.73413 9.4636 2.05252C9.69416 2.37092 9.81365 2.75627 9.80368 3.14925C9.8181 3.39741 9.78015 3.64583 9.69229 3.87836L9.23659 5.04292C9.15397 5.273 9.12623 5.51921 9.15558 5.76191C9.1877 6.00427 9.27425 6.23623 9.40875 6.44039C9.5535 6.6376 9.74028 6.80017 9.95558 6.91634C10.1774 7.03206 10.4244 7.0912 10.6746 7.08849V7.05811Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button tabindex="0" class="button share-action" type="button">Facebook</button>
</div>
<div class="action-icon">
<button tabindex="0" class="button share-action" type="button"><svg role="img" width="21" height="16" viewbox="0 0 21 16" fill="none" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.22192 2.20503C2.36754 1.77115 2.78269 1.45455 3.26639 1.45455H17.9332C18.4169 1.45455 18.8321 1.77118 18.9777 2.2051L10.5999 8.02107L2.22192 2.20503ZM2.16639 3.94198V13.4545C2.16639 14.0529 2.66307 14.5455 3.26639 14.5455H17.9332C18.5365 14.5455 19.0332 14.0529 19.0332 13.4545V3.94206L11.0204 9.50462C10.7679 9.67991 10.4318 9.67991 10.1793 9.50462L2.16639 3.94198ZM20.4999 2.55809V13.4545C20.4999 14.8562 19.3465 16 17.9332 16H3.26639C1.85304 16 0.699707 14.8562 0.699707 13.4545V2.54545C0.699707 1.14379 1.85304 0 3.26639 0H17.9332C19.3407 0 20.4904 1.13441 20.4998 2.52818C20.5 2.53816 20.5001 2.54813 20.4999 2.55809Z"></path>
</g></svg></button>
</div>
<div class="action-label">
<button tabindex="0" class="button share-action" type="button">Email</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</article>
</div>
</div>
<div class="single-post-section comments-section">
<div class="full-container-border"></div>
<div class="container">
<div class="comments-section-title">
18 Comments
</div>
<div class="visibility-check"></div>
<div class="comment-input-wrap">
<form method="post" class="form comment-input" novalidate="">
<div class="comment-input-head">
<div class="user-head">
<a>
<div class="profile-img-wrap">
<picture style="display: flex;"><source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_66,h_66,c_fill,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack.com%2Fimg%2Favatars%2Flogged-out.png" /><img src="https://substackcdn.com/image/fetch/w_66,h_66,c_fill,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack.com%2Fimg%2Favatars%2Flogged-out.png" sizes="100vw" alt="" srcset="" /></picture>
</div></a>
</div>
</div>
<div class="comment-input-right">
<textarea data-gramm="false" data-gramm_editor="false" data-enable-grammarly="false" name="body" placeholder="Write a comment…" style="height: 104px;"></textarea>
<div id="error-container"></div>
<div class="comment-button-container"></div>
</div>
</form>
<div role="dialog" class="modal typography out gone popup">
<div class="modal-table">
<div class="modal-row">
<div class="modal-cell modal-content">
<div class="container">
<button data-testid="close-modal" class="button modal-btn modal-exit-btn no-margin" type="button" tabindex="0"><svg role="img" width="20" height="20" viewbox="0 0 20 20" fill="none" stroke-width="1" stroke="#666666" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M15 5L5 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 5L15 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</g></svg></button>
<div class="profile-updater-modal">
<div class="profile-updater">
<h2 class="page-title profile-updater-title">
Create your profile
</h2>
<div class="profile-photo-wrap">
<img src="https://substackcdn.com/image/fetch/w_144,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack.com%2Fimg%2Favatars%2Flogged-out.png" /><button type="button" class="button" tabindex="0"><input type="file" name="photo" accept="image/*" /></button>
<div class="add-photo-fab">
<div class="add-photo-fab-inner">
<button type="button" class="button" tabindex="0"><svg role="img" style="height: 12px; width: 12px;" width="12" height="12" viewbox="0 0 14 14" fill="#fff" stroke-width="1" stroke="#fff" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M7 0V7M7 14V7M7 7H14H0"></path>
</g></svg></button>
</div>
</div>
</div>
<form action="/api/v1/user/profile" method="post" class="form" novalidate="">
<label for="name">Your name</label><input type="text" placeholder="Your name…" name="name" value="" class="profile-name" /><label for="bio">Your bio</label>
<textarea placeholder="Say something about yourself…" name="bio" class="profile-bio"></textarea><input type="email" placeholder="Your email…" name="email" class="profile-email" /><label class="profile-signup-checkbox"><input type="checkbox" name="free_signup" checked="checked" /> Subscribe to the newsletter</label><input type="hidden" name="photo_url" /><input type="hidden" name="user_id" value="" /><input type="hidden" name="needs_photo" value="false" /><input type="hidden" name="token" />
<div id="error-container"></div>
<p class="left hidden">
0 subscriptions will be displayed on your profile (<a>edit</a>)
</p>
<div class="modal-ctas">
<p class="skip hidden">
<a class="small">Skip for now</a>
</p><button class="button primary" type="submit" tabindex="0">Save &amp; Post Comment</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div role="dialog" class="modal typography out gone popup">
<div class="modal-table">
<div class="modal-row">
<div class="modal-cell modal-content">
<div class="container">
<button data-testid="close-modal" class="button modal-btn modal-exit-btn no-margin" type="button" tabindex="0"><svg role="img" width="20" height="20" viewbox="0 0 20 20" fill="none" stroke-width="1" stroke="#666666" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M15 5L5 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 5L15 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</g></svg></button>
<div class="paywall modal-paywall">
<h2 class="paywall-title">
Only paid subscribers can comment on this post
</h2>
<div class="paywall-login">
<a href="https://substack.com/sign-in?redirect=%2Fp%2Fno-really-why-cant-we-have-raw-udp&amp;for_pub=computerenhance&amp;change_user=false" native="true">Already a paid subscriber? <b>Sign in</b></a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div role="dialog" class="modal typography out gone finish-magic-login-modal popup">
<div class="modal-table">
<div class="modal-row">
<div class="modal-cell modal-content">
<div class="container">
<button data-testid="close-modal" class="button modal-btn modal-exit-btn no-margin" type="button" tabindex="0"><svg role="img" width="20" height="20" viewbox="0 0 20 20" fill="none" stroke-width="1" stroke="#666666" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M15 5L5 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 5L15 15" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
</g></svg></button>
<h4>
Check your email
</h4>
<p>
For your security, we need to re-authenticate you.
</p>
<p>
Click the link we sent to , or <a href="https://substack.com/sign-in?redirect=%2Fp%2Fno-really-why-cant-we-have-raw-udp&amp;for_pub=computerenhance&amp;with_password=true" native="true">click here to sign in</a>.
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="comment-list">
<div class="comment-list-items">
<div class="comment">
<div id="comment-7548116" class="comment-anchor"></div>
<div id="comment-7548116-reply" class="comment-anchor"></div>
<table class="comment-content">
<tr>
<td class="comment-head">
<div class="profile-hover-wrapper">
<div class="user-head">
<a href="https://substack.com/profile/16851368-hasen-judy">
<div class="profile-img-wrap">
<picture style="display: flex;"><source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_66,h_66,c_fill,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack.com%2Fimg%2Favatars%2Flogged-out.png" /><img src="https://substackcdn.com/image/fetch/w_66,h_66,c_fill,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack.com%2Fimg%2Favatars%2Flogged-out.png" sizes="100vw" alt="" srcset="" /></picture>
</div></a>
</div>
</div>
</td>
<td class="comment-rest">
<div class="comment-meta">
<div class="profile-hover-wrapper">
<span class="commenter-name"><a href="javascript:void(0)">Hasen Judy</a></span>
</div><a href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp/comment/7548116" native="true">Jul 5</a>
</div>
<div class="comment-body">
<p>
<span>My sense is that the game they are playing is blame management and plausible deniability.</span>
</p>
<p>
<span>Without https, it becomes plausible for banks and other websites where security is paramount to blame the web standards for lacking a way to secure connections when they leak sensitive user data.</span>
</p>
<p>
<span>So what the committees and browser vendors really wants is a way for the browsers to easily know that all connections with this site are "secured". Now, if information leaks, the blame is solely on the site operators.</span>
</p>
<p>
<span>Currently they can do this if the site uses https.</span>
</p>
<p>
<span>If you introduce UDP to the mix, and tell them "I will encrypt the packets myself", then the browser has no way to tell whether the connection is secure or not, so they will default to telling the user that this website uses an insecure connection.</span>
</p>
<p>
<span>This would not be so problematic, except I think they want to eventually deprecate non-secure connections.</span>
</p>
<p>
<span>Efficiency and simplicity is the last thing they care about. They will only care about it when someone demonstrates the existence of a clearly superior web application that cannot be implemented without a certain feature. I think this is why wasm got standarized.</span>
</p>
<div role="button" class="show-all-toggle">
<div class="show-all-toggle-label">
Expand full comment
</div>
</div>
</div>
<div class="comment-actions">
<span><a href="javascript:void(0)" class="like-button">
<div class="reaction-container">
<span><svg role="img" width="24" height="24" viewbox="0 0 24 24" fill="#000000" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="animation">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart">
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 0C1.46 6.7 1.33 10.28 4 13l8 8 8-8c2.67-2.72 2.54-6.3.42-8.42z"></path></svg>
</g></svg><svg role="img" width="14" height="14" viewbox="0 0 24 24" fill="transparent" stroke-width="1.5" stroke="#757575" xmlns="http://www.w3.org/2000/svg" style="height: 14px; width: 14px;">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="transparent" stroke="#757575" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart">
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 0C1.46 6.7 1.33 10.28 4 13l8 8 8-8c2.67-2.72 2.54-6.3.42-8.42z"></path></svg>
</g></svg></span>
</div><span class="like-count">3</span></a></span><span><a href="javascript:void(0)">Reply</a></span><span><a href="javascript:void(0)">Collapse</a></span>
</div>
</td>
</tr>
</table>
<div class="more-replies-container">
<a href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp/comment/7548116" class="more-replies">1 reply</a>
</div>
<div class="comment-list-collapser">
<div class="comment-list-collapser-line"></div>
</div>
</div>
<div class="comment">
<div id="comment-7548783" class="comment-anchor"></div>
<div id="comment-7548783-reply" class="comment-anchor"></div>
<table class="comment-content">
<tr>
<td class="comment-head">
<div class="profile-hover-wrapper">
<div class="user-head">
<a href="https://substack.com/profile/25100449-todor-nikolov">
<div class="profile-img-wrap">
<picture style="display: flex;"><source type="image/webp" srcset="https://substackcdn.com/image/fetch/w_66,h_66,c_fill,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1a22c5-383b-4b5a-a87a-a94c1b95c491_144x144.png" /><img src="https://substackcdn.com/image/fetch/w_66,h_66,c_fill,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fce1a22c5-383b-4b5a-a87a-a94c1b95c491_144x144.png" sizes="100vw" alt="" srcset="" /></picture>
</div></a>
</div>
</div>
</td>
<td class="comment-rest">
<div class="comment-meta">
<div class="profile-hover-wrapper">
<span class="commenter-name"><a href="javascript:void(0)">Todor Nikolov</a></span>
</div><a href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp/comment/7548783" native="true">Jul 5</a>
</div>
<div class="comment-body">
<p>
<span>Create your own client app. This is very much trying to fit a square peg into a round hole.</span>
</p>
<p>
<span>If you want to, you can even give your client app an address bar, and let others use your app for their servers. Then you won't even need to touch html or css or JavaScript.</span>
</p>
<div role="button" class="show-all-toggle">
<div class="show-all-toggle-label">
Expand full comment
</div>
</div>
</div>
<div class="comment-actions">
<span><a href="javascript:void(0)" class="like-button">
<div class="reaction-container">
<span><svg role="img" width="24" height="24" viewbox="0 0 24 24" fill="#000000" stroke-width="1" stroke="#000" xmlns="http://www.w3.org/2000/svg" class="animation">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart">
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 0C1.46 6.7 1.33 10.28 4 13l8 8 8-8c2.67-2.72 2.54-6.3.42-8.42z"></path></svg>
</g></svg><svg role="img" width="14" height="14" viewbox="0 0 24 24" fill="transparent" stroke-width="1.5" stroke="#757575" xmlns="http://www.w3.org/2000/svg" style="height: 14px; width: 14px;">
<g>
<title></title><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewbox="0 0 24 24" fill="transparent" stroke="#757575" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart">
<path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 0C1.46 6.7 1.33 10.28 4 13l8 8 8-8c2.67-2.72 2.54-6.3.42-8.42z"></path></svg>
</g></svg></span>
</div><span class="like-count">2</span></a></span><span><a href="javascript:void(0)">Reply</a></span><span><a href="javascript:void(0)">Collapse</a></span>
</div>
</td>
</tr>
</table>
<div class="comment-list-collapser">
<div class="comment-list-collapser-line"></div>
</div>
</div>
</div>
</div><a href="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp/comments" class="more-comments">16 more comments…</a>
</div>
</div>
<div class="visibility-check"></div>
<div class="subscribe-footer">
<div class="container">
<h1>
Ready for more?
</h1>
<form action="/api/v1/free?nojs=true" method="post" class="form" novalidate="">
<input type="hidden" name="first_url" value="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp" /><input type="hidden" name="first_referrer" /><input type="hidden" name="current_url" value="https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp" /><input type="hidden" name="current_referrer" /><input type="hidden" name="referral_code" /><input type="hidden" name="source" value="subscribe_footer" />
<div class="sideBySideWrap">
<input type="email" name="email" placeholder="Type your email…" /><button class="button rightButton primary subscribe-btn" type="submit" tabindex="0"><b class="button-text">Subscribe</b></button>
</div>
<div id="error-container"></div>
<div class="subtle-help-text below-input"></div>
</form>
</div>
</div>
</div>
<script type="text/javascript" async="async" src="https://www.googleadservices.com/pagead/conversion_async.js"></script>
<script type="text/javascript" async="async" src="https://www.googletagmanager.com/gtag/js?id=AW-316245675&amp;l=localGaDataLayer&amp;cx=c"></script>
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=undefined&amp;l=localGaDataLayer"></script>
<script type="text/javascript" async="async" src="https://googleads.g.doubleclick.net/pagead/viewthroughconversion/316245675/?random=1657117739678&amp;cv=9&amp;fst=1657117739678&amp;num=1&amp;bg=ffffff&amp;guid=ON&amp;resp=GooglemKTybQhCsO&amp;u_h=1117&amp;u_w=1728&amp;u_ah=1117&amp;u_aw=1728&amp;u_cd=30&amp;u_his=2&amp;u_tz=480&amp;u_java=false&amp;u_nplug=0&amp;u_nmime=0&amp;gtm=2oa6t0&amp;sendb=1&amp;ig=1&amp;data=event%3Dgtag.config&amp;frm=0&amp;url=https%3A%2F%2Fwww.computerenhance.com%2Fp%2Fno-really-why-cant-we-have-raw-udp&amp;tiba=No%20really%2C%20why%20can't%20we%20have%20raw%20UDP%20in%20JavaScript%3F&amp;hn=www.googleadservices.com&amp;async=1&amp;rfmt=3&amp;fmt=4"></script>
</div>
<div class="footer-wrap publication-footer">
<div class="footer themed-background">
<div class="container">
<div class="footer-blurbs">
<div class="footer-copyright-blurb">
© 2022 Casey Muratori
</div>
<div class="footer-terms-blurb">
<a href="https://www.computerenhance.com/privacy" native="true">Privacy</a><a href="/tos" native="true">Terms</a><a href="https://substack.com/ccpa#personal-data-collected" native="true">Collection notice</a>
</div>
</div>
<div class="footer-buttons">
<a native="true" href="https://substack.com/signup?utm_source=substack&amp;utm_medium=web&amp;utm_content=footer" class="footer-substack-cta start-publishing"><svg role="img" width="1000" height="1000" viewbox="0 0 1000 1000" fill="#FF6719" stroke-width="1" stroke="none" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M764.166 348.371H236.319V419.402H764.166V348.371Z"></path>
<path d="M236.319 483.752V813.999L500.231 666.512L764.19 813.999V483.752H236.319Z"></path>
<path d="M764.166 213H236.319V284.019H764.166V213Z"></path>
</g></svg> Publish on Substack</a><a native="true" href="https://substack.com/app/app-store-redirect?utm_campaign=app-marketing&amp;utm_content=web-footer-button" class="footer-substack-cta get-the-app"><svg role="img" width="24" height="24" viewbox="0 0 24 24" fill="#000" stroke-width="1" stroke="none" xmlns="http://www.w3.org/2000/svg">
<g>
<title></title>
<path d="M17.851 11.9011C17.861 11.125 18.0671 10.364 18.4502 9.68899C18.8334 9.01396 19.381 8.44682 20.0422 8.04031C19.6222 7.44042 19.068 6.94672 18.4238 6.59845C17.7796 6.25018 17.063 6.05691 16.3311 6.03401C14.7696 5.87011 13.2559 6.96835 12.4602 6.96835C11.6491 6.96835 10.4241 6.05028 9.10485 6.07742C8.25156 6.10499 7.41996 6.35312 6.69107 6.79764C5.96219 7.24216 5.36088 7.86791 4.94574 8.61392C3.14746 11.7274 4.48882 16.3032 6.21144 18.82C7.07331 20.0523 8.08059 21.4289 9.3986 21.3801C10.6884 21.3266 11.1701 20.5577 12.7269 20.5577C14.2693 20.5577 14.7212 21.3801 16.066 21.3491C17.4499 21.3266 18.3219 20.1112 19.1535 18.8672C19.7728 17.9891 20.2493 17.0186 20.5654 15.9916C19.7614 15.6516 19.0752 15.0823 18.5925 14.3549C18.1098 13.6275 17.8519 12.7741 17.851 11.9011Z"></path>
<path d="M15.3113 4.3788C16.0659 3.47293 16.4376 2.3086 16.3476 1.13306C15.1948 1.25414 14.1298 1.80513 13.3651 2.67623C12.9911 3.10179 12.7047 3.59687 12.5223 4.13318C12.3398 4.66949 12.2648 5.2365 12.3016 5.8018C12.8782 5.80774 13.4487 5.68276 13.97 5.43627C14.4913 5.18978 14.9499 4.82821 15.3113 4.3788Z"></path>
</g></svg> Get the app</a>
</div>
<div class="footer-slogan-blurb">
<a href="https://substack.com" native="true">Substack</a>&#160;is the home for great writing
</div>
</div>
</div>
</div>
</div>
<div style="transform: translateY(0px);" class="tw-fixed tw-bottom-2.5 tw-right-2.5 tw-left-2.5 md:tw-left-auto md:tw-bottom-4 md:tw-right-4 md:tw-pl-4 tw-z-10"></div>
</div>
<script src="https://js.sentry-cdn.com/c41771aeccbb43fbbffbc4755e65c9be.min.js" crossorigin="anonymous"></script>
<script>
<![CDATA[
window._preloads = {"isEU":false,"language":"en","country":"SG","base_url":"https://www.computerenhance.com","stripe_publishable_key":"pk_live_vNnuGHOFnt4mM7V9PuCAAPJz","captcha_site_key":"6LdYbsYZAAAAAIFIRh8X_16GoFRLIReh-e-q6qSa","pub":{"apple_pay_disabled":false,"author_id":11696674,"byline_images_enabled":true,"bylines_enabled":true,"chartable_token":null,"community_enabled":true,"copyright":"Casey Muratori","cover_photo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/50b378a5-f40c-4862-83fe-fdc9d5812319_800x800.png","created_at":"2022-04-27T02:52:56.913Z","custom_domain_optional":false,"custom_domain":"www.computerenhance.com","default_comment_sort":"best_first","default_coupon":null,"default_group_coupon":null,"default_show_guest_bios":true,"email_banner_url":null,"email_from_name":null,"email_from":null,"embed_tracking_disabled":false,"explicit":false,"expose_paywall_content_to_search_engines":true,"fb_pixel_id":null,"fb_site_verification_token":null,"flagged_as_spam":false,"founding_subscription_benefits":[],"free_subscription_benefits":["Everything but the ability to comment."],"ga_pixel_id":null,"google_site_verification_token":null,"google_tag_manager_token":null,"hero_image":null,"hero_text":"Technology, systems, interviews, commentary.","hide_intro_subtitle":null,"hide_intro_title":null,"hide_podcast_feed_link":false,"homepage_type":"newspaper","id":865289,"image_thumbnails_always_enabled":false,"invite_only":false,"keywee_pixel_id":null,"language":"en","logo_url_wide":null,"logo_url":null,"minimum_group_size":4,"moderation_enabled":true,"name":"Computer, Enhance!","page_enabled":false,"paid_subscription_benefits":["Subscriptions are only necessary if you wish to comment."],"parent_about_page_enabled":true,"parent_publication_id":null,"parsely_pixel_id":null,"payments_state":"disabled","paywall_free_trial_enabled":false,"podcast_art_url":null,"podcast_byline":null,"podcast_description":null,"podcast_enabled":false,"podcast_feed_url":null,"podcast_title":null,"post_preview_limit":null,"require_clickthrough":false,"rss_feed_url":null,"rss_website_url":null,"show_pub_podcast_tab":false,"show_recs_on_homepage":true,"sibling_rank":null,"subdomain":"computerenhance","subscriber_invites":0,"support_email":null,"theme_var_background_pop":"#FF6B00","theme_var_color_links":false,"theme_var_cover_bg_color":null,"trial_end_override":null,"twitter_pixel_id":null,"type":"newsletter","post_reaction_faces_enabled":true,"theme":{"publication_id":865289,"background_pop_color":null,"cover_bg_color":null,"web_bg_color":"#ffffff","color_links":null,"font_preset_heading":null,"font_preset_body":"fancy_serif","font_family_headings":null,"font_family_body":null,"font_family_ui":null,"font_size_body_desktop":null,"print_secondary":null,"custom_css_web":null,"custom_css_email":null},"plans":null,"stripe_user_id":"acct_1L5yrrGLUmfFtA9K","stripe_country":"US","stripe_publishable_key":"pk_live_51L5yrrGLUmfFtA9KmAQU38ppg8UXTEpMaYqTR5oYZChIKphozBYlUA0RcesZv3W6QQ4VtZ6J71Pq6onUhw8nnml500pBRCcQRj","author_name":"Casey Muratori","author_photo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/4a3d02ef-2cd1-4704-89e6-7cd174389c6b_586x622.png","author_bio":"Lead programmer at Molly Rocket, Inc.","has_child_publications":false,"has_posts":false,"has_recommendations":true,"first_post_date":"2022-07-05T02:58:16.304Z","has_podcast":false,"has_free_podcast":false,"has_subscriber_only_podcast":false,"has_community_content":true,"twitter_screen_name":"cmuratori","twitter_share_on_publish_opt_in":true,"twitter_permissions":"write","threads_v2_enabled":false,"rankingDetail":"Launched a day ago","rankingDetailFreeIncluded":"Hundreds of readers","contributors":[{"name":"Casey Muratori","role":"admin","owner":true,"user_id":11696674,"photo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/4a3d02ef-2cd1-4704-89e6-7cd174389c6b_586x622.png"}],"tier":2,"no_follow":false,"no_index":false,"can_set_google_site_verification":true,"can_have_sitemap":true,"hide_intro_popup_for_crawlers":false,"can_have_sitemap_page":false,"draft_plans":[{"id":"yearly30usd","object":"plan","active":true,"aggregate_usage":null,"amount":3000,"amount_decimal":"3000","billing_scheme":"per_unit","created":1654118543,"currency":"usd","interval":"year","interval_count":1,"livemode":true,"metadata":{"substack":"yes"},"nickname":"$30 a year","product":"prod_LnaA05HKNMkXEZ","tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":null,"usage_type":"licensed"},{"id":"monthly5usd","object":"plan","active":true,"aggregate_usage":null,"amount":500,"amount_decimal":"500","billing_scheme":"per_unit","created":1654118542,"currency":"usd","interval":"month","interval_count":1,"livemode":true,"metadata":{"substack":"yes"},"nickname":"$5 a month","product":"prod_LnaA50PhbDtTLF","tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":null,"usage_type":"licensed"}],"base_url":"https://www.computerenhance.com","hostname":"www.computerenhance.com","is_on_substack":false,"parent_publication":null,"child_publications":[],"sibling_publications":[],"sections":[{"id":21901,"created_at":"2022-07-05T06:12:55.385Z","updated_at":"2022-07-05T06:12:55.385Z","publication_id":865289,"name":"Interviews","description":"A subsection of \"Computer, Enhance!\" exclusively for interview series.","slug":"interviews","is_podcast":false,"is_live":true,"is_default_on":true,"sibling_rank":1,"port_status":"success","logo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/3ef7f8b9-9bac-4b5c-be0a-0c8ef5ebede3_800x800.png","podcastSettings":null}],"subscribeCardVersionHash":"9332a5696421a982be5205c1444237ea","section":null},"user":null,"freeSignupUserId":null,"freeSignupEmail":null,"freeSignup":null,"token":null,"staffContactId":null,"inviteOnly":null,"referralCode":null,"referralCoupon":null,"hide_intro_popup":true,"referralCampaign":null,"twitterEmail":null,"twitterToken":null,"domainInfo":{"isSubstack":false,"customDomain":"www.computerenhance.com"},"experimentFeatures":{"saved_posts":null,"freewall":"treatment","change_comment_gift_copy":"gift_user_sub_to_pub","subscribe_cta_prompt_enabled":"control","ios_app_marketing":null,"writer_reengagement":"control","subscribe_show_card_on_file":null},"experimentExposures":{"subscribe_cta_prompt_enabled":"control"},"siteConfigs":{"reader_onboarding_enable_subscribe_button":"NONE","profile_reader_onboarding":"treatment","polls_enabled":true,"podcast_post_page":true,"use_new_onboarding_email_import":"NONE","reader-onboarding-promoted-pub":737237,"continue_support_cta_emails_15d_after_expiry":false,"free_signup_confirmation_behavior":"default","selection_sharing":"NONE","tts_visible_in_app":true,"trending_posts_enabled":false,"activity_emails_v3":false,"cashtags_enabled":true,"end_of_post_recommendations":"control","post_ufi_refresh":true,"social_context_features":true,"like_activity_start_time":1653592864,"no_contest_charge_disputes":false,"saved_posts_enabled":false,"recommendations_announcement_url":"https://on.substack.com/p/recommendations","comp_expiry_email_new_copy":"NONE","free_unlock_required":false,"tts_enabled":true,"header_anchor_widgets":true,"amp_emails_enabled":false,"bundled_migrations_test":false,"minimum_ios_version":null,"bitcoin_enabled":false,"public_podcast_rss_feed_only_free_visible":false,"show_entire_square_image":false,"hide_subscriber_count":false,"email_recipients_batch_limit":5000,"publication_author_display_override":"","reader_onboarding_after_subscription_flow":"NONE","generate_pdf_tax_report":false,"threads_v2_visible":false,"press_kit_enabled":false,"web_inbox_migration":false,"reader_onboarding_in_email_login_flow":"treatment","include_pdf_invoice":false,"voiceover_enabled":true,"audio_embeds_enabled":true,"pub_creation_captcha_behavior":"risky_pubs_or_rate_limit","tax_integration_enabled":false,"subscribe_show_card_on_file":"NONE","first_party_click_tracking":true,"publisher_banner":"","app_inbox_v2_enabled":false,"delay_twitter":"NONE","tiktok_embed_enabled":true,"link_tracking_load_test":false,"writer_reengagement":"experiment","skip_welcome_email":false,"free_subscriber_email_campaign_drip":"control","ios_pause_email_default":false,"dont_show_guest_byline":false,"like_comments_enabled":true,"video_posts_enabled":false,"podcast_post_email":true,"use_elastic_audio_transcoder":true,"activity_feed_enabled":false,"generated_database_maintenance_mode":false,"paginate_email_recipients":true,"email_ufi_enabled":false,"disallow_spammy_comment_edits":false,"raise_prices_2":"NONE","welcome_screen_blurb_override":"","include_bottom_pixel":true,"show_email_app_install_button":true,"like_posts_enabled":true,"email_header_footer":"original_flow","history_bucket_unit":"month","twitter_player_card_enabled":true,"history_max_iterations":10,"history_paging_enabled":true,"show_notes_editor":false,"custom_target_origin":"","podcast_emails_play_on_substack":false,"exempt_from_gtm_filter":false,"max_image_upload_mb":32,"allow_moderation_sampling_mode":false,"allow_filtering_moderation_reasons":false,"photo_dna_enabled":false,"round_square_images":false,"publication_ban_sample_rate":0,"reader_referrals_feature_enabled":false,"batched_link_emails":"treatment","subscribe_captcha_behavior":"never","post_page_conversion":"NONE","import_verification_limit":3873,"continue_support_cta_in_newsletter_emails":false,"end_of_post_publication_recommendation":"control","tax_report_enable_stripe_fee_lineitem":true},"noIndex":false,"post":{"id":62549671,"publication_id":865289,"type":"newsletter","title":"No really, why can't we have raw UDP in JavaScript?","social_title":null,"section_id":null,"search_engine_title":null,"search_engine_description":null,"subtitle":"In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS.","slug":"no-really-why-cant-we-have-raw-udp","post_date":"2022-07-05T02:58:16.304Z","podcast_url":"","podcast_art_url":null,"podcast_duration":null,"video_upload_id":null,"podcast_upload_id":null,"audience":"everyone","should_send_free_preview":false,"write_comment_permissions":"everyone","show_guest_bios":true,"free_unlock_required":false,"default_comment_sort":null,"canonical_url":"https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp","reactions":{"\u2764":12},"top_exclusions":[],"pins":[],"section_pins":[],"next_slug":null,"prev_slug":null,"cover_image":"https://substackcdn.com/image/fetch/h_600,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg","cover_image_is_square":false,"videoUpload":null,"podcastUpload":null,"voiceover_upload_id":null,"voiceoverUpload":null,"description":"In my opinion, the pat answers about security are incomplete. I'd like to see a detailed writeup of specifically why a raw UDP API cannot be made as secure as current HTTPS.","body_html":"<div class=\"captioned-image-container\"><figure><a class=\"image-link image2\" target=\"_blank\" rel=\"nofollow\" href=\"https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg\"><picture><source type=\"image/webp\" srcset=\"https://substackcdn.com/image/fetch/w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1456w\" sizes=\"100vw\"><img src=\"https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg\" width=\"1456\" height=\"971\" data-attrs=\"{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg&quot;,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7578043,&quot;alt&quot;:&quot;A sculpture of a cartoon character stuck in a pipe.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false}\" class=\"sizing-normal\" alt=\"A sculpture of a cartoon character stuck in a pipe.\" title=\"A sculpture of a cartoon character stuck in a pipe.\" srcset=\"https://substackcdn.com/image/fetch/w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 424w, https://substackcdn.com/image/fetch/w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 848w, https://substackcdn.com/image/fetch/w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1272w, https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F43e258db-6164-4e47-835f-d11f10847d9d_5616x3744.jpeg 1456w\" sizes=\"100vw\"><\/picture><\/a><\/figure><\/div><p>By now I <a href=\"https://twitter.com/cmuratori/status/1543874684868931584\">should know better<\/a> than to ask on Twitter for a \u201Crigorous analysis\u201D of anything. As George W. Bush said, \u201CFool me once, shame on you\u2026 <a href=\"https://www.youtube.com/watch?v=ntwdH3Q54ZY\">fool me can\u2019t fooled again<\/a>.\u201D<\/p><p>I don\u2019t want to be \u201Cfool me can\u2019t get fooled again\u201D, so I officially give up on technical tweets. Today\u2019s the last day I will ever post anything technical on Twitter, I promise. Instead, you will be forced to endure yet another Substack, so I can post 3,000-word posts that no one will read.<\/p><p>Here we go:<\/p><h2>Why have a browser raw UDP API?<\/h2><p>The goal with raw UDP is very simple: better performance and security on the server side.<\/p><p>HTTPS is an unbaked sausage made by grinding pure text HTTP with TLS and encasing the result in an arbitrary selection of third-party animal intestine\u2026 err, I mean, \u201Chighly secure\u201D certificates provided by arbitrarily selected certificate providers. Implementing HTTPS is a massive amount of code that is inexorably slow. It is not only theoretically difficult to secure completely, but is <a href=\"https://www.openssl.org/news/vulnerabilities.html\">insecure in practice<\/a> in popular implementations available to the public.<\/p><p>Oh, and the certificate authorities are also insecure, by the way - but that\u2019s <a href=\"https://en.wikipedia.org/wiki/DigiNotar\">another story<\/a> (and <a href=\"https://decoded.avast.io/luigicamastra/backdoored-client-from-mongolian-ca-monpass/\">another<\/a>, and <a href=\"https://www.computerworld.com/article/2507090/firm-points-finger-at-iran-for-ssl-certificate-theft.html\">another<\/a>, and <a href=\"https://sslmate.com/resources/certificate_authority_failures\">\u2026<\/a>)<\/p><p>It also relied (up until recently) on TCP, which, unless you plan to write a completely custom network stack for every type of server/NIC you ever use, requires the underlying kernel to understand and track network connections. This means that you inherit substantial overhead, and perhaps vulnerabilities as well, from the TCP/IP substrate before you even begin to write your server code.<\/p><p>If you were a large company with significant academic and engineering resources, you might instead want to design your own private secure protocol that:<\/p><ol><li><p>Uses encryption you control, so it cannot be bypassed by hacking the certificate authority,<\/p><\/li><li><p>Uses UDP to avoid having OS connection state on the server side, and<\/p><\/li><li><p>Uses a well-designed, known packet structure to improve throughput and reduce security vulnerabilities from HTTP/TLS parsing.<\/p><\/li><\/ol><p>The first thing on that list is half-possible now. Although there\u2019s nothing you can (ever<a class=\"footnote-anchor\" id=\"footnote-anchor-1\" href=\"#footnote-1\">1<\/a>) do to avoid man-in-the-middle attacks the very first time someone interacts with your server, web APIs have long made it possible to store data on the client for later use. One use for that data would be storing your own set of public keys.<\/p><p>So even using nothing newer than XHR and cookies, you could theoretically add your own layer of encryption to anything you send to the server. This would ensure that any subsequent hack of the certificate authority could not inspect or modify your packets. It\u2019d be much less efficient than rolling your own top-to-bottom, because now you pay the entire cost for your encryption <em>and<\/em> TLS. But you <em>can <\/em>do it.<\/p><p>It\u2019s slow, but possible. Call it <em>half-possible<\/em>, like I did above.<\/p><p>The second thing on the list is sort-of possible now as well. If you can somehow manage to use <a href=\"https://en.wikipedia.org/wiki/HTTP/3\">HTTP/3<\/a> exclusively as your target platform, you will still be talking HTTP but you\u2019ll be doing it over UDP instead of TCP, and can manage connection state however you wish without OS intervention.<\/p><p>It is probably unrealistic to assume that you could do this in practice today. If you didn\u2019t care about broad compatibility, you probably wouldn\u2019t be deploying on the web anyway, so presumably the current adoption of HTTP/3 is insufficient. But at least it <em>exists<\/em>, and perhaps if adoption continues to grow, <em>eventually<\/em> it will be possible to require HTTP/3 without losing a significant number of users. For now, it\u2019s only something you can do on the side - you still have to have a traditional HTTPS fallback.<\/p><p>Which brings us to the third item on the list, and the real sticking point. As far as I\u2019m aware, no current or planned future Web API ever lets you do number three. There are many new web \u201Ctechnologies\u201D swarming around the custom packet idea (<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API\">WebRTC<\/a>, <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API\">WebSockets<\/a>, <a href=\"https://github.com/w3c/webtransport\">WebTransport<\/a>), but to the best of my knowledge, all of them require an HTTPS connection to be made first, so your \u201Ccustom packet\u201D servers still need to implement all of HTTPS anyway.<\/p><h2>What is the deployment scenario?<\/h2><p>I can imagine someone raising the following objection at this point: \u201CIf you don\u2019t support HTTPS on the server, how do you serve the WASM/JavaScript/whatever with the custom packet logic in the first place?\u201D<\/p><p>That\u2019s a reasonable question.<\/p><p>The answer is, the two most logical deployment scenarios I can think of both involve a separate server (or process) for the initial HTTPS transaction.<\/p><p>The first is what I imagine would be the most common: you upload to a CDN a traditional web package containing the PWA-style web worker necessary to do your own custom packet logic. The CDN serves this (static) content everywhere for you. They obviously implement HTTPS already, because that\u2019s what they do for a living, and they\u2019re not your servers anyway so you don\u2019t care.<\/p><p>The second would be less common, but plausible: you run your own CDN-equivalent, because <a href=\"https://knowyourmeme.com/memes/chuck-norris-facts\">you\u2019re just that hard core<\/a>. But you expect that your HTTPS code is more vulnerable than your custom code, since HTTPS is vastly more complicated and has ridiculous things in it like arbitrary text parsing, which no one in their right mind would ever put into a \u201Csecure\u201D protocol. So you cabin your HTTPS server instances into their own restricted processes or own machines entirely. This prevents exploits of the HTTPS code from affecting anything other than newly connecting users - existing users (who are only talking to your custom servers) remain unharmed.<\/p><p>In neither scenario do you actually include HTTPS code in any of the processes running your actual secure server.<\/p><h2>What precedent has been set by other \u201Csecure\u201D APIs in the browser?<\/h2><p>So that\u2019s the hopefully-at-least-somewhat-convincing explanation of why someone might want raw UDP. Now the question is, can raw UDP be provided by a browser in a way that is \u201Csecure\u201D?<\/p><p>I\u2019m putting a lot of these words in scare quotes because browsers <em>aren\u2019t<\/em> secure for any serious definition of that word, and hopefully that is overwhelmingly obvious to everyone who has ever used one. But just to be clear about the landscape, there are two different ways browsers are not secure:<\/p><ol><li><p>The web as a platform consists of massive, overlapping, poorly-specified APIs that require millions of lines of code to fully implement. As a result, browsers inexorably have <a href=\"https://www.mozilla.org/en-US/security/known-vulnerabilities/firefox/\">an effectively infinite number of security exploits<\/a> waiting to be found.<\/p><\/li><li><p>Browsers include the ability, sans exploit, to transmit information from the client computer to any number of remote servers. Without the ability to control this behavior, the user\u2019s data could be misappropriated.<\/p><\/li><\/ol><p>Clearly, for raw UDP, we only care about the second one of these. The first one happens in browsers all the time already and there\u2019s no reason to suspect that raw UDP would somehow have more implementation code vulnerabilities on average than any other part of the sprawling browser substrate.<\/p><p>So the question is, assuming the browser <em>has not<\/em> been exploited, what is the security standard for web features, and can raw UDP be implemented under that standard or not?<\/p><p>As a point of comparison, I will use the example of the current camera/microphone/location policy as it presently exists. That will be our \u201Cgold standard\u201D, since if it were not considered \u201Csecure\u201D by web implementers, presumably it would not have been knowingly shipped in web browsers everywhere for the past several years.<\/p><p>As everyone who uses a web browser knows, a web site at present is allowed to ask you for permission, temporarily or permanently (your choice), to access your camera, microphone, and location data. Once you say \u201Cyes\u201D to any one of these things, that site can transmit that data anywhere in the world, and use it for any purpose, trivially.<\/p><p>Allow me to provide a worked example.<\/p><p>Suppose I partner with Jeffrey Toobin to make a cybersex conduit site for people who, like him, see the value in quickly switching tabs away from your work meetings to get down to some <em>real<\/em> business. We launch cyberballsdeep.net, and it\u2019s a big success.<\/p><p>When a user visits our site, they see at most two security-related things:<\/p><ol><li><p>An allow/deny request for access to the microphone and camera, and<\/p><\/li><li><p>A lock icon indicating that the connection has been signed by a third party warranting that this connection is end-to-end encrypted from the user\u2019s machine to some server somewhere with the secure keys for cyberballsdeep.net.<\/p><\/li><\/ol><p>Assuming you click \u201Callow\u201D - which you have to in order to use the service - the servers at cyberballsdeep.net can now do anything they want with your (very sensitive) video data. They can, for example, record you while you are toobin\u2019 and play it back at any time, anywhere, at their discretion. They could play it on a billboard in Times Square, they could send it to your spouse - anything goes.<\/p><p>So the \u201Csecurity standard\u201D that you are getting, in practice, exactly mirrors the two things you saw:<\/p><ol><li><p>You know your sensitive data will not be captured unless you click \u201Callow\u201D, and<\/p><\/li><li><p>You know that nobody will be able to see your sensitive data unless either cyberballsdeep.net or the issuing certificate authority let them (either intentionally, or unintentionally if they\u2019ve been hacked).<\/p><\/li><\/ol><p>That\u2019s it. You don\u2019t know anything else. In practice, you basically have no security guarantees other than a warrant that your sensitive data will go to a particular named party <em>first<\/em> before it goes somewhere else.<\/p><p>Hopefully we can all agree that this extremely low bar for security is the only hurdle one should have to clear in order to dismiss concerns of \u201Csecurity\u201D as a reason not to implement a feature in a W3C spec. It\u2019s not much, but it is <em>something<\/em>.<\/p><h2>Can raw UDP meet this security standard?<\/h2><p>OK, finally, with all that out of the way, this is what I actually wanted someone to point me to <a href=\"https://twitter.com/cmuratori/status/1543874684868931584\">when I asked about this on Twitter<\/a>. I just wanted to see that someone, somewhere, had worked out exactly why UDP could not be made to fit the same security model considered acceptable across other basic web features already deployed and considered \u201Csecure\u201D.<\/p><p>Since nobody sent me such a thing, I am still stuck with my own security modeling, with nothing to compare against. My model goes something like this:<\/p><p>Step one - the \u201Callow/deny\u201D step - is easy for raw UDP to provide. The browser is still sitting between the JavaScript/WASM layer and the OS sockets layer, so it can ensure that inbound and outbound packets are filtered any way the browser wishes.<\/p><p>This means that it would be trivial for a browser to only allow UDP packets to and from servers that the user has authorized, as it does with microphone, camera, and location data. Any site that wishes to access raw UDP simply provides a hostname to the browser, and the browser asks the user whether they wish to allow the page to communicate with that site.<\/p><p>Furthermore, since the browser already allows the page to send as much HTTPS data as it wants back to the originating site, one could optionally allow any site to send UDP packets back to its own (exact) originating IP without asking the user. This is not necessary for raw UDP to work, but I can\u2019t think of any violation of \u201Cstep one\u201D that would happen as a result, so it could be considered.<\/p><p>Note that this is <em>not<\/em> true for something like camera/microphone/location data. Those are additional data sources to which the page gets access, so if anything, raw UDP permission is <em>less<\/em> dangerous in terms of user permission, since at no time does the page itself get additional access to the user\u2019s data, regardless of whether they allow UDP communication.<\/p><p>Which brings us to step two.<\/p><p>As far as I can tell, there\u2019s actually nothing special about step two. The original web page was served by HTTPS, obviously, since that\u2019s the only way the browser supports getting WASM/JavaScript downloaded in the first place. So the originating server and code are already exactly as \u201Csecure\u201D as they would be in any other scenario.<\/p><p>The user had to affirmatively allow the destination name, so the page can only send UDP to a specifically approved endpoint.<\/p><p>So the only question is, <em>can the user be sure that the data sent to that endpoint is encrypted such that only the endpoint or the certificate authority can decrypt it?<\/em><\/p><p>I can\u2019t know the hivemind of a W3C committee (thank the heavens). But if I had to guess, I would suspect that this is why they didn\u2019t want to allow raw UDP (or raw TCP for that matter). In their mind, it probably seems <em>less secure<\/em> than HTTPS to allow a web page to implement its own secure UDP protocol.<\/p><p>However, to my mind, this is based upon a flawed assumption. That assumption is that somehow web implementers <em>can<\/em> be trusted to deploy their encryption keys securely, but <em>cannot<\/em> be trusted to deploy their protocol securely.<\/p><p>To be more specific, HTTPS can be intercepted trivially if the attacker A) has a machine on the route between the endpoints and B) has access to the server\u2019s keys, or any certificate authority\u2019s signing capability. (A) either happens or it doesn\u2019t - there\u2019s no way to control it - so (B) is really the entire question.<\/p><p>So the notion that allowing web pages to use UDP for transmission is less secure than HTTPS seems to me to be predicated on the notion that web developers can be trusted to do something complicated in one place (run a set of servers without leaking keys), but also cannot be trusted to do something complicated in another (download, for example, a JavaScript UDP encryption library and use it).<\/p><p>Stated alternately, the hard constraint on the client side that you can\u2019t roll your packet code \u201Cfor security reasons\u201D is nowhere to be found on the server side. There is no requirement anywhere in W3C or anywhere else that says your web server has to be\u2026 well\u2026 anything at all, really. You can just go ahead and write your own code from top to bottom. You can even have a dedicated web page on your site that has the entire cryptographic key set for the server posted on it for people to cut-and-paste, so everyone can impersonate your server to anyone, anywhere, at any time. You can leave a thumb drive with your keys at the bar. You can generate your keys with a random seed of 0x000000000000000000. Anything goes.<\/p><p>Nobody seems to be panicked about this. Nobody has pushed the policy that the W3C should standardize on a specific web server deployment that you are forced to use, or a set of n of them made by Google/Mozilla/Apple, or what have you. It is just assumed that everyone is allowed to write their own <em>server<\/em> packet handling, but that no one is allowed to write their own <em>client<\/em> packet handling.<\/p><p>So that\u2019s what I would like explained. Internet, justify this!<\/p><h2>Appendix A.1.2b subsection 12: What about destination consent?<\/h2><p>I have seen people mention (but not support) a claim that raw UDP would cause \u201Cdenial of service\u201D problems because malicious web pages would send UDP packets to random servers in an attempt to overload them. This claim seems completely baseless to me, because there is no reason why you can\u2019t employ the relevant XHR DDoS restrictions to UDP. If DDoS was the concern, just require that UDP packets be sent exclusively within the same domain as the originating code.<\/p><p>Furthermore, you could restrict the port ranges of raw web UDP to some assigned range. A new port range could be explicitly reserved <em>just for raw web UDP<\/em> if that makes people more comfortable, so it could literally be discarded at the gateway on any network that doesn\u2019t want to support raw UDP for web, making it easier to deal with than UDP attacks from native code and viruses which can choose their ports at will.<\/p><p>At that point, I fail to see how raw UDP from the browser could be significantly more dangerous than XHR, unless I am missing some particularly clever use of UDP. And again, <em>that\u2019s why I asked for writeups in my original tweet<\/em>. I\u2019m totally willing to believe I\u2019m missing something, but I want to see a complete technical explanation about what it is.<\/p><p>Now, none of this is the same as saying I can\u2019t see how you would perform DDoS attacks with raw UDP. I certainly can. I just can\u2019t see how you would perform them <em>more easily than with XHR, <\/em>which obviously is considered \u201Csecure\u201D<em>.<\/em><\/p><p>As a simple example, suppose a commercial CDN distributes the payload of ddosfuntimes.com. On the main page, there\u2019s an XHR to target.ddosfuntimes.com. Even though the CDN is a completely different set of IP addresses as target.ddosfuntimes.com, this is completely legal under XHR policy.<\/p><p>The owners of ddosfuntimes.com can go ahead and set the IP address in their DNS records to point target.ddosfuntimes.com at any server they want, and they will receive all the XHR traffic from every browser that visits the page. And to the best of my knowledge, there isn\u2019t a damn thing the target can do about that.<\/p><p>So unless I\u2019m missing something, XHR already allows you to target any website you wish with unwanted traffic from anyone who visits your site. So why the concern about UDP?<\/p><div class=\"footnote\" id=\"footnote-1\"><a href=\"#footnote-anchor-1\" class=\"footnote-number\" contenteditable=\"false\">1<\/a><div class=\"footnote-content\"><p>This is way off topic, but in case it struck people as odd: all secure systems have a root trust problem. At some point you have to get <em>something<\/em> from <em>somebody<\/em> that you will just blindly trust. This is the root of the chain of trust, and unfortunately, there\u2019s really nothing you can do to make it secure. You just have to hope that this initial exchange is trusted.<\/p><p>So in the case of web browsers, you have to keep in mind that HTTPS doesn\u2019t actually guarantee you anything beyond a chain of trust. You are implicitly trusting that a) nobody messed with the browser when you downloaded it, b) none of the certificate authorities trusted by that browser download have been compromised, c) the certificate for signing browser root certificate updates hasn\u2019t itself been compromised.<\/p><p>Etc., etc.<\/p><p>So in general, when we talk about adding security to a protocol, we can only talk about securing it <em>up to a point<\/em>. No matter what we do, there will never be a way for it to be <em>completely<\/em> secure, because the chain of trust is not infinite, and any of its endpoints (in this case, the browser itself or any certificate authority) can lie to you for as long as it takes for a security firm to catch them doing it.<\/p><\/div><\/div>","truncated_body_text":"By now I should know better than to ask on Twitter for a \u201Crigorous analysis\u201D of anything. As George W. Bush said, \u201CFool me once, shame on you\u2026 fool me can\u2019t fooled again.\u201D I don\u2019t want to be \u201Cfool me can\u2019t get fooled again\u201D, so I officially give up on technical tweets. Today\u2019s the last day I will ever post anything technical on Twitter, I promise. Instea\u2026","wordcount":2918,"comment_count":18,"publishedBylines":[{"id":11696674,"name":"Casey Muratori","previous_name":null,"photo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/4a3d02ef-2cd1-4704-89e6-7cd174389c6b_586x622.png","bio":"Lead programmer at Molly Rocket, Inc.","profile_set_up_at":"2022-04-10T02:13:34.688Z","publicationUsers":[{"id":779290,"user_id":11696674,"publication_id":839621,"role":"admin","public":true,"is_primary":true,"publication":{"id":839621,"name":"Molly Movie Club","subdomain":"mollymovieclub","custom_domain":"www.mollymovieclub.com","custom_domain_optional":false,"hero_text":"@cmuratori and @aerettberg lead discussions about movies past and present, terrific and terrible, classic and forgettable.","logo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/bfef397c-db37-4c32-aa8e-35d400ad460c_1280x1280.png","author_id":86947332,"theme_var_background_pop":"#99A2F1","created_at":"2022-04-09T17:27:56.655Z","rss_website_url":null,"email_from_name":"Molly Movie Club","copyright":"Molly Rocket Incorporated","founding_plan_name":"Movie Mogul","community_enabled":true,"invite_only":false}},{"id":805843,"user_id":11696674,"publication_id":865289,"role":"admin","public":true,"is_primary":false,"publication":{"id":865289,"name":"Computer, Enhance!","subdomain":"computerenhance","custom_domain":"www.computerenhance.com","custom_domain_optional":false,"hero_text":"Technology, systems, interviews, commentary.","logo_url":null,"author_id":11696674,"theme_var_background_pop":"#FF6B00","created_at":"2022-04-27T02:52:56.913Z","rss_website_url":null,"email_from_name":null,"copyright":"Casey Muratori","founding_plan_name":null,"community_enabled":true,"invite_only":false}}],"twitter_screen_name":"cmuratori","is_guest":false}],"reaction":null,"truncated_description":null,"hasCashtag":false,"truncated_body_html":null,"post_paywall_content_for_google":null,"is_saved":false},"truncatedPost":null,"comments":[{"id":7548116,"body":"My sense is that the game they are playing is blame management and plausible deniability.\n\nWithout https, it becomes plausible for banks and other websites where security is paramount to blame the web standards for lacking a way to secure connections when they leak sensitive user data.\n\nSo what the committees and browser vendors really wants is a way for the browsers to easily know that all connections with this site are \"secured\". Now, if information leaks, the blame is solely on the site operators. \n\nCurrently they can do this if the site uses https.\n\nIf you introduce UDP to the mix, and tell them \"I will encrypt the packets myself\", then the browser has no way to tell whether the connection is secure or not, so they will default to telling the user that this website uses an insecure connection.\n\nThis would not be so problematic, except I think they want to eventually deprecate non-secure connections.\n\nEfficiency and simplicity is the last thing they care about. They will only care about it when someone demonstrates the existence of a clearly superior web application that cannot be implemented without a certain feature. I think this is why wasm got standarized.","publication_id":865289,"post_id":62549671,"user_id":16851368,"ancestor_path":"","type":"comment","deleted":false,"date":"2022-07-05T05:16:44.324Z","edited_at":null,"reply_from_post_id":null,"status":"published","pinned_by_user_id":null,"name":"Hasen Judy","photo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/a8fa8e25-484f-48c4-a753-5958a9ad6475_318x245.png","reactions":{"\u2764":3},"reactor_names":[],"reaction":null,"children":[],"bans":[],"suppressed":false,"user_banned":false,"user_banned_for_comment":false,"metadata":{"is_author":false,"eligibleForGift":false},"score":4,"reported_by_user":false,"childrenSummary":"1 reply"},{"id":7548783,"body":"Create your own client app. This is very much trying to fit a square peg into a round hole.\nIf you want to, you can even give your client app an address bar, and let others use your app for their servers. Then you won't even need to touch html or css or JavaScript.","publication_id":865289,"post_id":62549671,"user_id":25100449,"ancestor_path":"","type":"comment","deleted":false,"date":"2022-07-05T06:45:36.380Z","edited_at":null,"reply_from_post_id":null,"status":"published","pinned_by_user_id":null,"name":"Todor Nikolov","photo_url":"https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/ce1a22c5-383b-4b5a-a87a-a94c1b95c491_144x144.png","reactions":{"\u2764":2},"reactor_names":[],"reaction":null,"children":[],"bans":[],"suppressed":false,"user_banned":false,"user_banned_for_comment":false,"metadata":{"is_author":false,"eligibleForGift":false},"score":3,"reported_by_user":false}],"post_reaction_token":null,"canonicalUrl":"https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp","inlineComments":false,"readerIsSearchCrawler":false,"selectionFromQuery":null,"embeddedPublications":null,"ogUrl":"https://www.computerenhance.com/p/no-really-why-cant-we-have-raw-udp","features":{}}
]]>
</script>
<script>
<![CDATA[
window._analyticsConfig = {"user":null,"properties":{"subdomain":"computerenhance","publication_id":865289,"has_plans":false,"pub_community_enabled":true,"parent_publication_id":null,"parent_publication_subdomain":null,"is_parent_publication":false,"section_name":null,"section_slug":null,"section_id":null,"section_is_podcast":null,"is_subscribed":false,"is_free_subscribed":false,"is_author":false,"is_contributor":false,"is_admin":false},"adwordsAccountId":"AW-316245675","adwordsEventSendTo":"Tf76CKqcyL4DEKuN5pYB"}
]]>
</script>
<script src="https://substackcdn.com/min/main.bundle.js?v=17a3f0-181d0ca8818" charset="utf-8"></script> <!-- Fallback tracking pixels -->
<noscript>
<div id="nojs-banner">
This site requires JavaScript to run correctly. Please <a href="https://enable-javascript.com/" target="_blank">turn on JavaScript</a> or unblock scripts
</div></noscript>
</body>
</html>