Files
nexus/sreweekly/articles/304/06-why-might-you-run-your-own-dns-server.html
2026-09-12 17:23:01 +08:00

395 lines
23 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 class="no-js" lang="en">
<head>
<meta charset="utf-8">
<title>Why might you run your own DNS server?</title>
<meta name="author" content="Julia Evans">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="description" content="Why might you run your own DNS server?">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:title" content='Why might you run your own DNS server?'>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://jvns.ca/blog/2022/01/05/why-might-you-run-your-own-dns-server-/" />
<meta property="og:site_name" content="Julia Evans" />
<link rel="canonical" href="https://jvns.ca/blog/2022/01/05/why-might-you-run-your-own-dns-server-/">
<link href="/favicon.ico" rel="icon">
<link href="/stylesheets/screen.css" rel="preload" type="text/css" as="style">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<link href="/stylesheets/print.css" media="print" rel="stylesheet" type="text/css">
<link href="/atom.xml" rel="alternate" title="Julia Evans" type="application/atom+xml">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous">
<script defer data-domain="jvns.ca" src="https://plausible.io/js/script.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js" integrity="sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>
<script defer type="text/javascript">
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=document.createElement("script");r.type="text/javascript",r.async=!0,r.src="https://cdn.heapanalytics.com/js/heap-"+e+".js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(r,a);for(var n=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","resetIdentity","removeEventProperty","setEventProperties","track","unsetEventProperty"],o=0;o<p.length;o++)heap[p[o]]=n(p[o])};
heap.load("2242143965");
</script>
</head>
<body>
<div id="skiptocontent">
<a href="#main">Skip to main content</a>
</div>
<div id="wrap">
<header role="banner">
<hgroup>
<h1><a href="/">Julia Evans</a></h1>
</hgroup>
<ul class="header-links">
<li><a href="/about">About</a></li>
<li><a href="/talks">Talks</a></li>
<li><a href="/projects/">Projects</a></li>
<li><a rel="me" href="https://social.jvns.ca/@b0rk">Mastodon</a></li>
<li><a href="https://bsky.app/profile/b0rk.jvns.ca">Bluesky</a></li>
<li><a href="https://github.com/jvns">Github</a></li>
</ul>
</header>
<nav role="navigation" class="header-nav"><ul class="main-navigation">
<li><a href="/categories/favorite/">Favorites</a></li>
<li><a href="/til/">TIL</a></li>
<li><a href="https://wizardzines.com">Zines</a></li>
<li class="subscription" data-subscription="rss"><a href="/atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
</ul>
</nav>
<div id="main">
<div id="content">
<div>
<article class="hentry" role="article">
<header>
<h1 class="entry-title">Why might you run your own DNS server?</h1>
<div class="post-tags">
•
<a class="post-tag" href="/categories/dns">dns</a> •
</div>
<p class="meta sans">
<time class="date" datetime="2022-01-05T06:42:51" pubdate data-updated="true">
January 5, 2022
</time>
</p>
</header>
<main>
<p>One of the things that makes DNS difficult to understand is that it&rsquo;s
<strong>decentralized</strong>. There are thousands (maybe hundreds of thousands? I don&rsquo;t know!) of authoritative nameservers, and at least
<a href="https://www.icann.org/en/blogs/details/ten-million-dns-resolvers-on-the-internet-22-3-2012-en">10 million resolvers</a>.
And they&rsquo;re running lots of different software! All these different servers
running software means that there&rsquo;s a lot of inconsistency in how DNS works,
which can cause all kinds of frustrating problems.</p>
<p>But instead of talking about the problems, I&rsquo;m interested in figuring out &ndash;
why is it a good thing that DNS is decentralized?</p>
<h3 id="why-is-it-good-that-dns-is-decentralized" class="post-heading">
<a href="#why-is-it-good-that-dns-is-decentralized">
why is it good that DNS is decentralized?
</a>
</h3>
<p>One reason is <strong>scalability</strong> &ndash; the decentralized design of DNS makes it
easier to scale and more resilient to failures. I find it really amazing that
DNS is still scaling well even though it&rsquo;s almost 40 years old. This is very
important but it&rsquo;s not what this post is about.</p>
<p>Instead, I want to talk about how the fact that it&rsquo;s decentralized means that
you can have <strong>control</strong> of how your DNS works. You can add more servers to the
giant complicated mess of DNS servers! Servers that you control!</p>
<p>Yesterday I <a href="https://twitter.com/b0rk/status/1478490484406468614">asked on Twitter</a> why you might
want to run your own DNS servers, and I got a lot of great answers that I
wanted to summarize here.</p>
<h3 id="you-can-run-2-types-of-dns-servers" class="post-heading">
<a href="#you-can-run-2-types-of-dns-servers">
you can run 2 types of DNS servers
</a>
</h3>
<p>There are 2 main types of DNS servers you can run:</p>
<ol>
<li>if you own a domain, you can run an <strong>authoritative nameserver</strong> for that domain</li>
<li>if you have a computer (or a company with lots of computers), you can run a <strong>resolver</strong> that&rsquo;s resolves DNS for those computers</li>
</ol>
<h3 id="dns-isn-t-a-static-database" class="post-heading">
<a href="#dns-isn-t-a-static-database">
DNS isn&rsquo;t a static database
</a>
</h3>
<p>I&rsquo;ve seen the &ldquo;phone book&rdquo; metaphor for DNS a lot, where domain names are like
names and IP addresses are like phone numbers.</p>
<p>This is an okay mental model to start with. But the &ldquo;phone book&rdquo; mental model
might make you think that if you make a DNS query for <code>google.com</code>, you&rsquo;ll
always get the same result. And that&rsquo;s not true at all!</p>
<p>Which record you get in reply to a DNS query can depend on:</p>
<ul>
<li>where you are in the world (maybe you&rsquo;ll get an IP address of a server that&rsquo;s physically closer to you!)</li>
<li>if you&rsquo;re on a corporate network (where you might be able to resolve internal domain names)</li>
<li>whether the domain name is considered &ldquo;bad&rdquo; by your DNS resolver (it might be blocked!)</li>
<li>the previous DNS query (maybe the DNS resolver is doing DNS-based load balancing to give you a different IP address every time)</li>
<li>whether you&rsquo;re using an airport wifi captive portal (airport wifi will resolve DNS records differently before you log in, it&rsquo;ll send you a special IP to redirect you)</li>
<li>literally anything</li>
</ul>
<p>A lot of the reasons you might want to control your own server are related to
the fact that DNS isn&rsquo;t a static database &ndash; there are a lot of choices you
might want to make about how DNS queries are handled (either for your domain or for your organization).</p>
<h3 id="reasons-to-run-an-authoritative-nameserver" class="post-heading">
<a href="#reasons-to-run-an-authoritative-nameserver">
reasons to run an authoritative nameserver
</a>
</h3>
<p>These reasons aren&rsquo;t in any particular order.</p>
<p>For some of these you don&rsquo;t necessarily have to run your own authoritative
nameserver, you can just choose an authoritative nameserver service that has
the features you want.</p>
<p>To be clear: there are lots of reasons <strong>not</strong> to run your own authoritative
nameserver &ndash; I don&rsquo;t run my own, and I&rsquo;m not trying to convince you that you
should. It takes time to maintain, your service might not be as reliable, etc.</p>
<p><strong>reason: security</strong></p>
<p><a href="https://twitter.com/thatcks/status/1478503078680838153">this tweet phrased it well</a>:</p>
<blockquote>
<p>[There&rsquo;s a] risk of an attacker gaining DNS change access through your vendor&rsquo;s customer
support people, who only want to be helpful. Or getting locked out from your
DNS (perhaps because of the lack of that). In-house may be easier to audit and
verify the contents.</p>
</blockquote>
<p><strong>reason: you like running bind/nsd</strong></p>
<p>One reason several people mentioned was &ldquo;I&rsquo;m used to writing zone files and
running <code>bind</code> or <code>nsd</code>, it&rsquo;s easier for me to just do that&rdquo;.</p>
<p>If you like the interface of bind/nsd but don&rsquo;t want to operate your own
server, a couple of people mentioned that you can also get the advantages of
bind by running a &ldquo;hidden primary&rdquo; server which stores the records, but serve
all of the actual DNS queries from a &ldquo;secondary&rdquo; server. Here are some pages
I found about configuring secondary DNS from from <a href="https://help.ns1.com/hc/en-us/articles/360017508173-Configuring-NS1-as-a-secondary-provider-a-k-a-Creating-secondary-zones-">NS1</a> and <a href="https://blog.cloudflare.com/secondary-dns-a-faster-more-resilient-way-to-serve-your-dns-records/">cloudflare</a> and <a href="https://help.dyn.com/standard-dns/dyn-secondary-dns-information/">Dyn</a> as an example.</p>
<p>I don&rsquo;t really know what the best authoritative DNS server to run is. I think
I&rsquo;ve only used nsd at work.</p>
<p><strong>reason: you can use new record types</strong></p>
<p>Some newer DNS record types aren&rsquo;t supported by all DNS services, but if you
run your own you can support any record types you want.</p>
<p><strong>reason: user interface</strong></p>
<p>You might not like the user interface (or API, or lack of API) of the DNS
service you&rsquo;re using. This is pretty related to the &ldquo;you like running BIND&rdquo;
reason &ndash; maybe you like the zone file interface!</p>
<p><strong>reason: you can fix problems yourself</strong></p>
<p>There are some obvious pros and cons to being able to fix problems yourself
when they arise (pro: you can fix the problem, con: you have to fix the
problem).</p>
<p><strong>reason: do something weird and custom</strong></p>
<p>You can write a DNS server that does anything you want, it doesn&rsquo;t have to just return a static set of records.</p>
<p>A few examples:</p>
<ul>
<li>Replit has a blog post about <a href="https://blog.replit.com/dns">why they wrote their own authoritative DNS server to handle routing</a></li>
<li><a href="https://nip.io">nip.io</a> maps 10.0.0.1.nip.io to 10.0.0.1</li>
<li>I wrote a custom DNS server for <a href="https://jvns.ca/blog/2021/12/15/mess-with-dns/">mess with dns</a></li>
</ul>
<p><strong>reason: to save money</strong></p>
<p>Authoritative nameservers seem to generally charge per million DNS queries. As
an example, at a quick glance it looks like Route 53 charges about $0.50 per
million queries and <a href="https://ns1.com/plans">NS1</a> charges about $8 per million queries.</p>
<p>I don&rsquo;t have the best sense for how many queries a large website&rsquo;s
authoritative DNS server can expect to actually need to resolve (what kinds of
sites get 1 billion DNS queries to their authoritative DNS server? Probably a
lot, but I don&rsquo;t have experience with that.). But a few people in the replies
mentioned cost as a reason.</p>
<p><strong>reason: you can change your registrar</strong></p>
<p>If you use a separate authoritative nameserver for your domain instead of your
registrar&rsquo;s nameserver, then when you move to a different registrar all you have
to do to get your DNS back up is to set your authoritative DNS server to the
right value. You don&rsquo;t need to migrate all your DNS records, which is a huge
pain!</p>
<p>You don&rsquo;t need to run your own nameserver to do this.</p>
<p><strong>reason: geo DNS</strong></p>
<p>You might want to return different IP addresses for your domain depending on
where the client is, to give them a server that&rsquo;s close to them.</p>
<p>This is a service lots of authoritative nameserver services offer, you don&rsquo;t
need to write your own to do this.</p>
<p><strong>reason: avoid denial of service attacks targeted at someone else</strong></p>
<p>Many authoritative DNS servers are shared. This means that if someone attacks
the DNS server for <code>google.com</code> or something and you happen to be using the
same authoritative DNS server, you could be affected even though the attack
wasn&rsquo;t aimed at you. For example, this <a href="https://en.wikipedia.org/wiki/DDoS_attack_on_Dyn">DDoS attack on Dyn</a> in 2016.</p>
<p><strong>reason: keep all of your configuration in one place</strong></p>
<p>One person mentioned that they like to keep all of their configuration (DNS
records, let&rsquo;s encrypt, nginx, etc) in the same place on one server.</p>
<p><strong>wild reason: use DNS as a VPN</strong></p>
<p>Apparently <a href="https://github.com/yarrick/iodine">iodine</a> is an authoritative DNS
server that lets you tunnel your traffic over DNS, if you&rsquo;re on a network that
only allows you to contact the outside world as a VPN.</p>
<h3 id="reasons-to-run-a-resolver" class="post-heading">
<a href="#reasons-to-run-a-resolver">
reasons to run a resolver
</a>
</h3>
<p><strong>reason: privacy</strong></p>
<p>If someone can see all your DNS lookups, they have a complete list of all the
domains you (or everyone from your organization) is visiting! You might prefer
to keep that private.</p>
<p><strong>reason: block malicious sites</strong></p>
<p>If you run your own resolver, you can refuse to resolve DNS queries (by just
not returning any results) for domains that you consider &ldquo;bad&rdquo;.</p>
<p>A few examples of resolvers that you can run yourself (or just use):</p>
<ul>
<li><a href="https://pi-hole.net/">Pi-Hole</a> blocks advertisers</li>
<li><a href="https://www.quad9.net/">Quad9</a> blocks domains that do malware/phishing/spyware. Cloudflare seems to have a <a href="https://developers.cloudflare.com/1.1.1.1/1.1.1.1-for-families">similar service</a></li>
<li>I imagine there&rsquo;s also corporate security software that blocks DNS queries for domains that host malware</li>
<li>DNS isn’t a static database. It’s very dynamic, and answers often depend in
real time on the IP address a query came from, current load on content
servers etc. That’s hard to do in real time unless you delegate serving those
records to the entity making those decisions.</li>
<li>DNS delegating control makes access control very simple. Everything under a
zone cut is controlled by the person who controls the delegated server, so
responsibility for a hostname is implicit in the DNS delegation.</li>
</ul>
<p><strong>reason: get dynamic proxying in nginx</strong></p>
<p>Here&rsquo;s a cool story from <a href="https://twitter.com/jordanorelli/status/1478795241876504577">this tweet</a>:</p>
<blockquote>
<p>I wrote a DNS server into an app and then set it as nginx’s resolver so that I could get dynamic backend proxying without needing nginx to run lua. Nginx sends DNS query to app, app queries redis and responds accordingly. It worked pretty great for what I was doing.</p>
</blockquote>
<p><strong>reason: avoid malicious resolvers</strong></p>
<p>Some ISPs run DNS resolvers that do bad things like nonexistent domains to an
IP they control that shows you ads or a weird search page that they control.</p>
<p>Using either a resolver you control or a different resolver that you trust
can help you avoid that.</p>
<p><strong>reason: resolve internal domains</strong></p>
<p>You might have an internal network with domains (like
<code>blah.corp.yourcompany.com</code>) that aren&rsquo;t on the public internet. Running your
own resolver for machines in the internal network makes it possible to access
those domains.</p>
<p>You can do the same thing on a home network, either to access local-only
services or to just get local addresses for services that are on the public
internet.</p>
<p><strong>reason: avoid your DNS queries being MITM&rsquo;d</strong></p>
<p>One person <a href="https://twitter.com/passcod/status/1478806468539269120">said</a>:</p>
<blockquote>
<p>I run a resolver on my LAN router that uses DNS over HTTPS for its upstream, so
IoT and other devices that don&rsquo;t support DoH or DoT don&rsquo;t spray plaintext DNS
outside</p>
</blockquote>
<h3 id="that-s-all-for-now" class="post-heading">
<a href="#that-s-all-for-now">
that&rsquo;s all for now
</a>
</h3>
<p>It feels important to me to explore the &ldquo;why&rdquo; of DNS, because it&rsquo;s such a
complicated messy system and I think most people find it hard to get motivated
to learn about complex topics if they don&rsquo;t understand why all this complexity
is useful.</p>
<small>
Thanks to Marie and Kamal for discussing this post, and to everyone on Twitter
who provided reasons
</small>
</main>
<footer>
<style type="text/css">
#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; display: inline;}
#mc_embed_signup {
display: inline;
}
#mc_embed_signup input.button {
background: #ff5e00;
display: inline;
color: white;
padding: 6px 12px;
}
</style>
<div class="sharing">
<style>
.form-inline {
display:flex; flex-flow: row wrap; justify-content: center;
}
.form-inline input, .form-inline span {
padding: 10px;
}
.form-inline input {
display:inline;
max-width:30%;
margin: 0 10px 0 0;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 5px;
padding: 10px;
}
button {
background-color: #f50;
box-shadow: none;
border: 0;
border-radius: 5px;
color: white;
padding: 5px 10px;
}
@media (max-width: 800px) {
.form-inline input {
margin: 10px 0;
max-width:100% !important;
}
.form-inline {
flex-direction: column;
align-items: stretch;
}
}
</style>
<div align="center">
<form class="form-inline" action="https://app.convertkit.com/forms/1052396/subscriptions" method="post" data-uid="8884355abb" data-format="inline" data-version="5">
<span> Want a weekly digest of this blog?</span>
<input name="email_address" type="text" placeholder="Email address" />
<button type="submit" data-element="submit">Subscribe</button>
</form>
</div>
</div>
<p class="meta">
<a class="basic-alignment left" href="https://jvns.ca/blog/2021/12/31/2021--year-in-review/" title="Previous Post: 2021: Year in review">2021: Year in review</a>
<a class="basic-alignment right" href="https://jvns.ca/blog/2022/01/11/how-to-find-a-domain-s-authoritative-nameserver/" title="Next Post: How to find a domain&#39;s authoritative nameservers">How to find a domain&#39;s authoritative nameservers</a>
</p>
</footer>
</article>
</div>
</div>
</div>
<nav role="navigation" class="footer-nav"> <a href="/">Archives</a>
</nav>
<footer role="contentinfo"><span class="credit">&copy; Julia Evans. </span>
<span>If you like this, you may like <a href="https://web.archive.org/web/20181228051203/http://www.uliaea.ca/">Ulia Ea</a> or, more seriously, this list of <a href="https://jvns.ca/blogroll">blogs I love</a> or some <a href="https://jvns.ca/bookshelf">books I've read</a>. <br>
<p class="rc-scout__text"><i class="rc-scout__logo"></i>
You might also like the <a class="rc-scout__link" href="https://www.recurse.com/scout/click?t=546ea46360584b522270b8c3e5d830f8">Recurse Center</a>, my very favorite programming community <a href="/categories/hackerschool/">(my posts about it)</a></p>
</span>
<style class="rc-scout__style" type="text/css">.rc-scout{display:block;padding:0;border:0;margin:0;}.rc-scout__text{display:block;padding:0;border:0;margin:0;height:100%;font-size:100%;}.rc-scout__logo{display:inline-block;padding:0;border:0;margin:0;width:0.85em;height:0.85em;background:no-repeat center url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012%2015%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2212%22%20height%3D%2210%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%221%22%20y%3D%221%22%20width%3D%2210%22%20height%3D%228%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%222%22%20width%3D%228%22%20height%3D%226%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%2361ae24%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%2361ae24%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%2361ae24%22%3E%3C%2Frect%3E%3Crect%20x%3D%223%22%20y%3D%225%22%20width%3D%222%22%20height%3D%221%22%20fill%3D%22%2361ae24%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%225%22%20width%3D%222%22%20height%3D%221%22%20fill%3D%22%2361ae24%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%229%22%20width%3D%224%22%20height%3D%223%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%221%22%20y%3D%2211%22%20width%3D%2210%22%20height%3D%224%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%220%22%20y%3D%2212%22%20width%3D%2212%22%20height%3D%223%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%223%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%225%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%227%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%228%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%229%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3C%2Fsvg%3E');}.rc-scout__link:link,.rc-scout__link:visited{color:#61ae24;text-decoration:underline;}.rc-scout__link:hover,.rc-scout__link:active{color:#4e8b1d;}</style>
</footer>
<script type="text/rocketscript">
(function(){
var twitterWidgets = document.createElement('script');
twitterWidgets.type = 'text/javascript';
twitterWidgets.async = true;
twitterWidgets.src = 'http://platform.twitter.com/widgets.js';
document.getElementsByTagName('head')[0].appendChild(twitterWidgets);
})();
</script>
</div>
</body>
</html>