362 lines
29 KiB
HTML
362 lines
29 KiB
HTML
|
|
||
|
|
||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
|
||
|
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
|
||
|
<title>Over the River and Through the Wood — Stem 1.8.1-maint documentation</title>
|
||
|
|
||
|
<link rel="stylesheet" href="../_static/haiku.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
<link rel="stylesheet" href="../_static/style.css" type="text/css" />
|
||
|
|
||
|
<script type="text/javascript">
|
||
|
var DOCUMENTATION_OPTIONS = {
|
||
|
URL_ROOT: '../',
|
||
|
VERSION: '1.8.1-maint',
|
||
|
COLLAPSE_INDEX: false,
|
||
|
FILE_SUFFIX: '.html',
|
||
|
HAS_SOURCE: true
|
||
|
};
|
||
|
</script>
|
||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
||
|
<link rel="shortcut icon" href="../_static/favicon.png"/>
|
||
|
<link rel="top" title="Stem 1.8.1-maint documentation" href="../index.html" />
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="header"><img class="rightlogo" src="../_static/logo.png" alt="Logo"/><h1 class="heading"><a href="../index.html">
|
||
|
<span>Stem Docs</span></a></h1>
|
||
|
<h2 class="heading"><span>Over the River and Through the Wood</span></h2>
|
||
|
</div>
|
||
|
<div class="topnav">
|
||
|
|
||
|
<p>
|
||
|
|
||
|
<ul id="navbar">
|
||
|
<li><a href="../index.html">Home</a></li>
|
||
|
<li><a href="../tutorials.html">Tutorials</a>
|
||
|
<ul>
|
||
|
<li><a href="the_little_relay_that_could.html">Hello World</a></li>
|
||
|
<li><a href="to_russia_with_love.html">Client Usage</a></li>
|
||
|
<li><a href="tortoise_and_the_hare.html">Event Listening</a></li>
|
||
|
<li><a href="#">Hidden Services</a></li>
|
||
|
<li><a href="mirror_mirror_on_the_wall.html">Tor Descriptors</a></li>
|
||
|
<li><a href="east_of_the_sun.html">Utilities</a></li>
|
||
|
<li><a href="down_the_rabbit_hole.html">Interpreter</a></li>
|
||
|
<li><a href="double_double_toil_and_trouble.html">Examples</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li><a href="../api.html">API</a>
|
||
|
<ul>
|
||
|
<li><a href="../api/control.html">stem.control</a></li>
|
||
|
<li><a href="../api/connection.html">stem.connection</a></li>
|
||
|
<li><a href="../api/socket.html">stem.socket</a></li>
|
||
|
<li><a href="../api/process.html">stem.process</a></li>
|
||
|
<li><a href="../api/response.html">stem.response</a></li>
|
||
|
<li><a href="../api/exit_policy.html">stem.exit_policy</a></li>
|
||
|
<li><a href="../api/version.html">stem.version</a></li>
|
||
|
<li><a href="../api.html#descriptors">Descriptors</a></li>
|
||
|
<li><a href="../api.html#utilities">Utilities</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem">Development</a>
|
||
|
<ul>
|
||
|
<li><a href="../faq.html">FAQ</a></li>
|
||
|
<li><a href="../change_log.html">Change Log</a></li>
|
||
|
<li><a href="https://github.com/torproject/stem/issues/">Bug Tracker</a></li>
|
||
|
<li><a href="https://jenkins.torproject.org/job/stem-tor-ci/">Jenkins</a></li>
|
||
|
<li><a href="../download.html">Download</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li><a href="../faq.html#where-can-i-get-help">Contact</a>
|
||
|
<ul>
|
||
|
<li><a href="https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev">Email List</a></li>
|
||
|
<li><a href="https://www.torproject.org/about/contact.html.en#irc">IRC</a></li>
|
||
|
<li><a href="https://www.atagar.com/contact/">Author</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</p>
|
||
|
|
||
|
</div>
|
||
|
<div class="content">
|
||
|
|
||
|
|
||
|
<div class="section" id="over-the-river-and-through-the-wood">
|
||
|
<h1>Over the River and Through the Wood<a class="headerlink" href="#over-the-river-and-through-the-wood" title="Permalink to this headline">¶</a></h1>
|
||
|
<p><a class="reference external" href="https://www.torproject.org/docs/hidden-services.html.en">Hidden services</a>
|
||
|
give you a way of providing a service without exposing your address. These
|
||
|
services are only accessible through Tor or <a class="reference external" href="https://tor2web.org/">Tor2web</a>,
|
||
|
and useful for a surprising number of things...</p>
|
||
|
<ul class="simple">
|
||
|
<li><strong>Hosting an anonymized site</strong>. This is usually the first thing that comes to
|
||
|
mind, and something we'll demonstrate in a sec.</li>
|
||
|
<li>Providing an <strong>endpoint Tor users can reach</strong> without exiting the Tor
|
||
|
network. This eliminates the risk of an unreliable or malicious exit getting
|
||
|
in the way. Great examples of this are <a class="reference external" href="http://arstechnica.com/security/2014/10/facebook-offers-hidden-service-to-tor-users/">Facebook</a>
|
||
|
(<em>facebookcorewwwi.onion</em>) and <a class="reference external" href="https://lists.torproject.org/pipermail/tor-talk/2010-August/003095.html">DuckDuckGo</a>
|
||
|
(<em>3g2upl4pq6kufc4m.onion</em>).</li>
|
||
|
<li><strong>Personal services</strong>. For instance you can host your home SSH server as a
|
||
|
hidden service to prevent eavesdroppers from knowing where you live while
|
||
|
traveling abroad.</li>
|
||
|
</ul>
|
||
|
<p><a class="reference external" href="https://tor2web.org/">Tor2web</a> provides a quick and easy way of seeing if
|
||
|
your hidden service is working. To use it simply replace the <strong>.onion</strong> of
|
||
|
your address with <strong>.tor2web.org</strong>...</p>
|
||
|
<a class="reference external image-reference" href="https://3g2upl4pq6kufc4m.tor2web.org/"><img alt="../_images/duck_duck_go_hidden_service.png" src="../_images/duck_duck_go_hidden_service.png" /></a>
|
||
|
<div class="section" id="running-a-hidden-service">
|
||
|
<span id="id2"></span><h2>Running a hidden service<a class="headerlink" href="#running-a-hidden-service" title="Permalink to this headline">¶</a></h2>
|
||
|
<p>Hidden services can be <a class="reference external" href="https://www.torproject.org/docs/tor-manual.html.en#_hidden_service_options">configured through your torrc</a>,
|
||
|
but Stem also provides some methods to easily work with them...</p>
|
||
|
<blockquote>
|
||
|
<div><ul class="simple">
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">create_hidden_service()</span></tt></li>
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">remove_hidden_service()</span></tt></li>
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">get_hidden_service_conf()</span></tt></li>
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">set_hidden_service_conf()</span></tt></li>
|
||
|
</ul>
|
||
|
</div></blockquote>
|
||
|
<p>The main threat to your anonymity when running a hidden service is the service
|
||
|
itself. Debug information for instance might leak your real address,
|
||
|
undermining what Tor provides. This includes the following example, <strong>do not
|
||
|
rely on it not to leak</strong>.</p>
|
||
|
<p>But with that out of the way lets take a look at a simple <a class="reference external" href="http://flask.pocoo.org/">Flask</a> example based on one by <a class="reference external" href="https://jordan-wright.github.io/blog/2014/10/06/creating-tor-hidden-services-with-python/">Jordan Wright</a>...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
|
||
|
<span class="kn">import</span> <span class="nn">shutil</span>
|
||
|
|
||
|
<span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Controller</span>
|
||
|
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
|
||
|
|
||
|
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
|
||
|
|
||
|
|
||
|
<span class="nd">@app.route</span><span class="p">(</span><span class="s">'/'</span><span class="p">)</span>
|
||
|
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
|
||
|
<span class="k">return</span> <span class="s">"<h1>Hi Grandma!</h1>"</span>
|
||
|
|
||
|
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">' * Connecting to tor'</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">with</span> <span class="n">Controller</span><span class="o">.</span><span class="n">from_port</span><span class="p">()</span> <span class="k">as</span> <span class="n">controller</span><span class="p">:</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
|
||
|
|
||
|
<span class="c"># All hidden services have a directory on disk. Lets put ours in tor's data</span>
|
||
|
<span class="c"># directory.</span>
|
||
|
|
||
|
<span class="n">hidden_service_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">controller</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">'DataDirectory'</span><span class="p">,</span> <span class="s">'/tmp'</span><span class="p">),</span> <span class="s">'hello_world'</span><span class="p">)</span>
|
||
|
|
||
|
<span class="c"># Create a hidden service where visitors of port 80 get redirected to local</span>
|
||
|
<span class="c"># port 5000 (this is where Flask runs by default).</span>
|
||
|
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">" * Creating our hidden service in </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">hidden_service_dir</span><span class="p">)</span>
|
||
|
<span class="n">result</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">create_hidden_service</span><span class="p">(</span><span class="n">hidden_service_dir</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="n">target_port</span> <span class="o">=</span> <span class="mi">5000</span><span class="p">)</span>
|
||
|
|
||
|
<span class="c"># The hostname is only available when we can read the hidden service</span>
|
||
|
<span class="c"># directory. This requires us to be running with the same user as tor.</span>
|
||
|
|
||
|
<span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">" * Our service is available at </span><span class="si">%s</span><span class="s">, press ctrl+c to quit"</span> <span class="o">%</span> <span class="n">result</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span>
|
||
|
<span class="k">else</span><span class="p">:</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">" * Unable to determine our service's hostname, probably due to being unable to read the hidden service directory"</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">try</span><span class="p">:</span>
|
||
|
<span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
|
||
|
<span class="k">finally</span><span class="p">:</span>
|
||
|
<span class="c"># Shut down the hidden service and clean it off disk. Note that you *don't*</span>
|
||
|
<span class="c"># want to delete the hidden service directory if you'd like to have this</span>
|
||
|
<span class="c"># same *.onion address in the future.</span>
|
||
|
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">" * Shutting down our hidden service"</span><span class="p">)</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">remove_hidden_service</span><span class="p">(</span><span class="n">hidden_service_dir</span><span class="p">)</span>
|
||
|
<span class="n">shutil</span><span class="o">.</span><span class="n">rmtree</span><span class="p">(</span><span class="n">hidden_service_dir</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>Now if we run this...</p>
|
||
|
<div class="highlight-python"><pre>% python example.py
|
||
|
* Connecting to tor
|
||
|
* Creating our hidden service in /home/atagar/.tor/hello_world
|
||
|
* Our service is available at uxiuaxejc3sxrb6i.onion, press ctrl+c to quit
|
||
|
* Running on http://127.0.0.1:5000/
|
||
|
127.0.0.1 - - [15/Dec/2014 13:05:43] "GET / HTTP/1.1" 200 -
|
||
|
* Shutting down our hidden service</pre>
|
||
|
</div>
|
||
|
<p>... we'll have a service we can visit via the <a class="reference external" href="https://www.torproject.org/download/download-easy.html.en">Tor Browser Bundle</a>...</p>
|
||
|
<img alt="../_images/hidden_service.png" src="../_images/hidden_service.png" />
|
||
|
</div>
|
||
|
<div class="section" id="hidden-service-authentication">
|
||
|
<span id="id3"></span><h2>Hidden service authentication<a class="headerlink" href="#hidden-service-authentication" title="Permalink to this headline">¶</a></h2>
|
||
|
<p>Hidden services you create can restrict their access, requiring in essence a
|
||
|
password...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Controller</span>
|
||
|
<span class="gp">>>> </span><span class="n">controller</span> <span class="o">=</span> <span class="n">Controller</span><span class="o">.</span><span class="n">from_port</span><span class="p">()</span>
|
||
|
<span class="gp">>>> </span><span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
|
||
|
<span class="gp">>>> </span><span class="n">response</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">create_ephemeral_hidden_service</span><span class="p">({</span><span class="mi">80</span><span class="p">:</span> <span class="mi">8080</span><span class="p">},</span> <span class="n">await_publication</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">basic_auth</span><span class="o">=</span><span class="p">{</span><span class="s">'bob'</span><span class="p">:</span> <span class="bp">None</span><span class="p">,</span> <span class="s">'alice'</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span>
|
||
|
<span class="gp">>>> </span><span class="n">response</span><span class="o">.</span><span class="n">service_id</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">client_auth</span>
|
||
|
<span class="go">('l3lnorirzn7hrjnw', {'alice': 'I6AMKiay+UkM5MfrvdnF2A', 'bob': 'VLsbrSGyrb5JYEvZmQ3tMg'})</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>To access this service users simply provide this credential to tor via their
|
||
|
torrc or SETCONF prior to visiting it...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">controller</span><span class="o">.</span><span class="n">set_conf</span><span class="p">(</span><span class="s">'HidServAuth'</span><span class="p">,</span> <span class="s">'l3lnorirzn7hrjnw.onion I6AMKiay+UkM5MfrvdnF2A'</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="section" id="ephemeral-hidden-services">
|
||
|
<span id="id4"></span><h2>Ephemeral hidden services<a class="headerlink" href="#ephemeral-hidden-services" title="Permalink to this headline">¶</a></h2>
|
||
|
<p>In the above example you may have noticed the note that said...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="c"># The hostname is only available when we can read the hidden service</span>
|
||
|
<span class="c"># directory. This requires us to be running with the same user as tor.</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>This has been a limitation of hidden services for years. However, as of version
|
||
|
0.2.7.1 Tor offers another style for making services called <strong>ephemeral hidden
|
||
|
services</strong>.</p>
|
||
|
<p>Ephemeral services can only be created through the controller, and only exist
|
||
|
as long as your controller is attached unless you provide the <strong>detached</strong>
|
||
|
flag. Controllers can only see their own ephemeral services, and ephemeral
|
||
|
services that are detached. In other words, attached ephemeral services can
|
||
|
only be managed by their own controller.</p>
|
||
|
<p>Stem provides three methods to work with ephemeral hidden services...</p>
|
||
|
<blockquote>
|
||
|
<div><ul class="simple">
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">list_ephemeral_hidden_services()</span></tt></li>
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">create_ephemeral_hidden_service()</span></tt></li>
|
||
|
<li><tt class="xref py py-func docutils literal"><span class="pre">remove_ephemeral_hidden_service()</span></tt></li>
|
||
|
</ul>
|
||
|
</div></blockquote>
|
||
|
<p>For example, with a ephemeral service our earlier example becomes as simple as...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Controller</span>
|
||
|
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
|
||
|
|
||
|
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
|
||
|
|
||
|
|
||
|
<span class="nd">@app.route</span><span class="p">(</span><span class="s">'/'</span><span class="p">)</span>
|
||
|
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
|
||
|
<span class="k">return</span> <span class="s">"<h1>Hi Grandma!</h1>"</span>
|
||
|
|
||
|
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">' * Connecting to tor'</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">with</span> <span class="n">Controller</span><span class="o">.</span><span class="n">from_port</span><span class="p">()</span> <span class="k">as</span> <span class="n">controller</span><span class="p">:</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
|
||
|
|
||
|
<span class="c"># Create a hidden service where visitors of port 80 get redirected to local</span>
|
||
|
<span class="c"># port 5000 (this is where Flask runs by default).</span>
|
||
|
|
||
|
<span class="n">response</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">create_ephemeral_hidden_service</span><span class="p">({</span><span class="mi">80</span><span class="p">:</span> <span class="mi">5000</span><span class="p">},</span> <span class="n">await_publication</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">" * Our service is available at </span><span class="si">%s</span><span class="s">.onion, press ctrl+c to quit"</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">service_id</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">try</span><span class="p">:</span>
|
||
|
<span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
|
||
|
<span class="k">finally</span><span class="p">:</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">" * Shutting down our hidden service"</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<p>Ephemeral hidden services do not touch disk, and as such are easier to work
|
||
|
with but require you to persist your service's private key yourself if you want
|
||
|
to reuse a '.onion' address...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
|
||
|
<span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Controller</span>
|
||
|
|
||
|
<span class="n">key_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s">'~/my_service_key'</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">with</span> <span class="n">Controller</span><span class="o">.</span><span class="n">from_port</span><span class="p">()</span> <span class="k">as</span> <span class="n">controller</span><span class="p">:</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
|
||
|
|
||
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">key_path</span><span class="p">):</span>
|
||
|
<span class="n">service</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">create_ephemeral_hidden_service</span><span class="p">({</span><span class="mi">80</span><span class="p">:</span> <span class="mi">5000</span><span class="p">},</span> <span class="n">await_publication</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">"Started a new hidden service with the address of </span><span class="si">%s</span><span class="s">.onion"</span> <span class="o">%</span> <span class="n">service</span><span class="o">.</span><span class="n">service_id</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">key_path</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">key_file</span><span class="p">:</span>
|
||
|
<span class="n">key_file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">service</span><span class="o">.</span><span class="n">private_key_type</span><span class="p">,</span> <span class="n">service</span><span class="o">.</span><span class="n">private_key</span><span class="p">))</span>
|
||
|
<span class="k">else</span><span class="p">:</span>
|
||
|
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">key_path</span><span class="p">)</span> <span class="k">as</span> <span class="n">key_file</span><span class="p">:</span>
|
||
|
<span class="n">key_type</span><span class="p">,</span> <span class="n">key_content</span> <span class="o">=</span> <span class="n">key_file</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">':'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||
|
|
||
|
<span class="n">service</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">create_ephemeral_hidden_service</span><span class="p">({</span><span class="mi">80</span><span class="p">:</span> <span class="mi">5000</span><span class="p">},</span> <span class="n">key_type</span> <span class="o">=</span> <span class="n">key_type</span><span class="p">,</span> <span class="n">key_content</span> <span class="o">=</span> <span class="n">key_content</span><span class="p">,</span> <span class="n">await_publication</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">"Resumed </span><span class="si">%s</span><span class="s">.onion"</span> <span class="o">%</span> <span class="n">service</span><span class="o">.</span><span class="n">service_id</span><span class="p">)</span>
|
||
|
|
||
|
<span class="nb">raw_input</span><span class="p">(</span><span class="s">'press any key to shut the service down...'</span><span class="p">)</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">remove_ephemeral_hidden_service</span><span class="p">(</span><span class="n">service</span><span class="o">.</span><span class="n">service_id</span><span class="p">)</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="section" id="hidden-service-descriptors">
|
||
|
<span id="id5"></span><h2>Hidden service descriptors<a class="headerlink" href="#hidden-service-descriptors" title="Permalink to this headline">¶</a></h2>
|
||
|
<p>Like relays, hidden services publish documents about themselves called <strong>hidden
|
||
|
service descriptors</strong>. These contain low level details for establishing
|
||
|
connections. Hidden service descriptors are available from the tor process via
|
||
|
its <tt class="xref py py-func docutils literal"><span class="pre">get_hidden_service_descriptor()</span></tt> method...</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Controller</span>
|
||
|
|
||
|
<span class="k">with</span> <span class="n">Controller</span><span class="o">.</span><span class="n">from_port</span><span class="p">(</span><span class="n">port</span> <span class="o">=</span> <span class="mi">9051</span><span class="p">)</span> <span class="k">as</span> <span class="n">controller</span><span class="p">:</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
|
||
|
|
||
|
<span class="c"># descriptor of duck-duck-go's hidden service (http://3g2upl4pq6kufc4m.onion)</span>
|
||
|
|
||
|
<span class="k">print</span><span class="p">(</span><span class="n">controller</span><span class="o">.</span><span class="n">get_hidden_service_descriptor</span><span class="p">(</span><span class="s">'3g2upl4pq6kufc4m'</span><span class="p">))</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<div class="highlight-python"><pre>% python print_duck_duck_go_descriptor.py
|
||
|
|
||
|
rendezvous-service-descriptor e5dkwgp6vt7axoozixrbgjymyof7ab6u
|
||
|
version 2
|
||
|
permanent-key
|
||
|
-----BEGIN RSA PUBLIC KEY-----
|
||
|
MIGJAoGBAJ/SzzgrXPxTlFrKVhXh3buCWv2QfcNgncUpDpKouLn3AtPH5Ocys0jE
|
||
|
aZSKdvaiQ62md2gOwj4x61cFNdi05tdQjS+2thHKEm/KsB9BGLSLBNJYY356bupg
|
||
|
I5gQozM65ENelfxYlysBjJ52xSDBd8C4f/p9umdzaaaCmzXG/nhzAgMBAAE=
|
||
|
-----END RSA PUBLIC KEY-----
|
||
|
secret-id-part bmsctib2pzirgo7cltlxdm5fxqcitt5e
|
||
|
publication-time 2015-05-11 20:00:00
|
||
|
protocol-versions 2,3
|
||
|
introduction-points
|
||
|
-----BEGIN MESSAGE-----
|
||
|
aW50cm9kdWN0aW9uLXBvaW50IHZzcm4ycGNtdzNvZ21mNGo3dGpxeHptdml1Y2Rr
|
||
|
NGtpCmlwLWFkZHJlc3MgMTc2LjkuNTkuMTcxCm9uaW9uLXBvcnQgOTAwMQpvbmlv
|
||
|
... etc...</pre>
|
||
|
</div>
|
||
|
<p>A hidden service's introduction points are a base64 encoded field that's
|
||
|
possibly encrypted. These can be decoded (and decrypted if necessary) with the
|
||
|
descriptor's
|
||
|
<tt class="xref py py-func docutils literal"><span class="pre">introduction_points()</span></tt>
|
||
|
method.</p>
|
||
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Controller</span>
|
||
|
|
||
|
<span class="k">with</span> <span class="n">Controller</span><span class="o">.</span><span class="n">from_port</span><span class="p">(</span><span class="n">port</span> <span class="o">=</span> <span class="mi">9051</span><span class="p">)</span> <span class="k">as</span> <span class="n">controller</span><span class="p">:</span>
|
||
|
<span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
|
||
|
<span class="n">desc</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_hidden_service_descriptor</span><span class="p">(</span><span class="s">'3g2upl4pq6kufc4m'</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">"DuckDuckGo's introduction points are...</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
|
||
|
|
||
|
<span class="k">for</span> <span class="n">introduction_point</span> <span class="ow">in</span> <span class="n">desc</span><span class="o">.</span><span class="n">introduction_points</span><span class="p">():</span>
|
||
|
<span class="k">print</span><span class="p">(</span><span class="s">' </span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s"> => </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">introduction_point</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">introduction_point</span><span class="o">.</span><span class="n">port</span><span class="p">,</span> <span class="n">introduction_point</span><span class="o">.</span><span class="n">identifier</span><span class="p">))</span>
|
||
|
</pre></div>
|
||
|
</div>
|
||
|
<div class="highlight-python"><pre>% python print_duck_duck_go_introduction_points.py
|
||
|
|
||
|
DuckDuckGo's introduction points are...
|
||
|
|
||
|
176.9.59.171:9001 => vsrn2pcmw3ogmf4j7tjqxzmviucdk4ki
|
||
|
104.131.106.181:9001 => gcl2kpqx5qnkpgxjf6x7ulqncoqj7ghh
|
||
|
188.166.58.218:443 => jeymnbhs2d6l2oib7jjvweavg45m6gju</pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
<div class="bottomnav">
|
||
|
</div>
|
||
|
|
||
|
<div class="footer">
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|