This commit is contained in:
emdee@spm.plastiras.org 2024-01-14 14:28:53 +00:00
parent 79b2296285
commit e41515a8a7
22 changed files with 1821 additions and 49 deletions

12
Makefile Normal file
View File

@ -0,0 +1,12 @@
LOCAL_DOCTEST=/usr/local/bin/toxcore_run_doctest3.bash
DOCTEST=${LOCAL_DOCTEST}
lint::
sh .pylint.sh
rsync::
bash .rsync.sh
doctest:
export PYTHONPATH=${PWD}
${DOCTEST} stem_examples.txt

167
docs/compare_flags.html Normal file
View File

@ -0,0 +1,167 @@
<!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>Comparing Directory Authority Flags &mdash; 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>Comparing Directory Authority Flags</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="../over_the_river.html">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="comparing-directory-authority-flags">
<h1>Comparing Directory Authority Flags<a class="headerlink" href="#comparing-directory-authority-flags" title="Permalink to this headline"></a></h1>
<a class="reference external image-reference" href="../double_double_toil_and_trouble.html"><img alt="../../_images/back.png" src="../../_images/back.png" /></a>
<p>Compares the votes of two directory authorities, in this case moria1 and
maatuska, with a special interest in the 'Running' flag.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">collections</span>
<span class="kn">import</span> <span class="nn">stem.descriptor</span>
<span class="kn">import</span> <span class="nn">stem.descriptor.remote</span>
<span class="kn">import</span> <span class="nn">stem.directory</span>
<span class="c"># Query all authority votes asynchronously.</span>
<span class="n">downloader</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">remote</span><span class="o">.</span><span class="n">DescriptorDownloader</span><span class="p">(</span>
<span class="n">document_handler</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">DocumentHandler</span><span class="o">.</span><span class="n">DOCUMENT</span><span class="p">,</span>
<span class="p">)</span>
<span class="c"># An ordered dictionary ensures queries are finished in the order they were</span>
<span class="c"># added.</span>
<span class="n">queries</span> <span class="o">=</span> <span class="n">collections</span><span class="o">.</span><span class="n">OrderedDict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">authority</span> <span class="ow">in</span> <span class="n">stem</span><span class="o">.</span><span class="n">directory</span><span class="o">.</span><span class="n">Authority</span><span class="o">.</span><span class="n">from_cache</span><span class="p">()</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="n">authority</span><span class="o">.</span><span class="n">v3ident</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">continue</span> <span class="c"># authority doesn&#39;t vote if it lacks a v3ident</span>
<span class="n">queries</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">downloader</span><span class="o">.</span><span class="n">get_vote</span><span class="p">(</span><span class="n">authority</span><span class="p">)</span>
<span class="c"># Wait for the votes to finish being downloaded, this produces a dictionary of</span>
<span class="c"># authority nicknames to their vote.</span>
<span class="n">votes</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">name</span><span class="p">,</span> <span class="n">query</span><span class="o">.</span><span class="n">run</span><span class="p">()[</span><span class="mi">0</span><span class="p">])</span> <span class="k">for</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">query</span><span class="p">)</span> <span class="ow">in</span> <span class="n">queries</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
<span class="c"># Get a superset of all the fingerprints in all the votes.</span>
<span class="n">all_fingerprints</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="n">vote</span> <span class="ow">in</span> <span class="n">votes</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
<span class="n">all_fingerprints</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">vote</span><span class="o">.</span><span class="n">routers</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
<span class="c"># Finally, compare moria1&#39;s votes to maatuska&#39;s votes.</span>
<span class="k">for</span> <span class="n">fingerprint</span> <span class="ow">in</span> <span class="n">all_fingerprints</span><span class="p">:</span>
<span class="n">moria1_vote</span> <span class="o">=</span> <span class="n">votes</span><span class="p">[</span><span class="s">&#39;moria1&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">routers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">fingerprint</span><span class="p">)</span>
<span class="n">maatuska_vote</span> <span class="o">=</span> <span class="n">votes</span><span class="p">[</span><span class="s">&#39;maatuska&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">routers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">fingerprint</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">moria1_vote</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">maatuska_vote</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;both moria1 and maatuska haven&#39;t voted about </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">fingerprint</span><span class="p">)</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">moria1_vote</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;moria1 hasn&#39;t voted about </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">fingerprint</span><span class="p">)</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">maatuska_vote</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;maatuska hasn&#39;t voted about </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">fingerprint</span><span class="p">)</span>
<span class="k">elif</span> <span class="s">&#39;Running&#39;</span> <span class="ow">in</span> <span class="n">moria1_vote</span><span class="o">.</span><span class="n">flags</span> <span class="ow">and</span> <span class="s">&#39;Running&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">maatuska_vote</span><span class="o">.</span><span class="n">flags</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;moria1 has the Running flag but maatuska doesn&#39;t: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">fingerprint</span><span class="p">)</span>
<span class="k">elif</span> <span class="s">&#39;Running&#39;</span> <span class="ow">in</span> <span class="n">maatuska_vote</span><span class="o">.</span><span class="n">flags</span> <span class="ow">and</span> <span class="s">&#39;Running&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">moria1_vote</span><span class="o">.</span><span class="n">flags</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;maatuska has the Running flag but moria1 doesn&#39;t: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">fingerprint</span><span class="p">)</span>
</pre></div>
</div>
<div class="highlight-python"><pre>% python compare_flags.py
maatuska has the Running flag but moria1 doesn't: 92FCB6748A40E6088E22FBAB943AB2DD743EA818
maatuska has the Running flag but moria1 doesn't: 6871F682350BA931838C0EC1E4A23044DAE06A73
maatuska has the Running flag but moria1 doesn't: E2BB13AA2F6960CD93ABE5257A825687F3973C62
moria1 has the Running flag but maatuska doesn't: 546C54E2A89D88E0794D04AECBF1AC8AC9DA81DE
moria1 has the Running flag but maatuska doesn't: DCAEC3D069DC39AAE43D13C8AF31B5645E05ED61
...</pre>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

View File

@ -0,0 +1,250 @@
<!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>Download Tor Descriptors &mdash; 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>Download Tor Descriptors</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="../over_the_river.html">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="download-tor-descriptors">
<h1>Download Tor Descriptors<a class="headerlink" href="#download-tor-descriptors" title="Permalink to this headline"></a></h1>
<a class="reference external image-reference" href="../double_double_toil_and_trouble.html"><img alt="../../_images/back.png" src="../../_images/back.png" /></a>
<p>Tor relays provide a mirror for the tor relay descriptors it has cached.
These are available from its ORPort using <a class="reference external" href="https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt">Tor's wire protocol</a>, and optionally
with http as well from a <a class="reference external" href="https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt">DirPort</a>.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Simple script to dowload a descriptor from Tor&#39;s ORPort or DirPort.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">collections</span>
<span class="kn">import</span> <span class="nn">getopt</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">stem</span>
<span class="kn">import</span> <span class="nn">stem.descriptor.remote</span>
<span class="kn">import</span> <span class="nn">stem.util.connection</span>
<span class="kn">import</span> <span class="nn">stem.util.tor_tools</span>
<span class="c"># By default downloading moria1&#39;s server descriptor from itself.</span>
<span class="n">DEFAULT_ARGS</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">&#39;descriptor_type&#39;</span><span class="p">:</span> <span class="s">&#39;server&#39;</span><span class="p">,</span>
<span class="s">&#39;fingerprint&#39;</span><span class="p">:</span> <span class="s">&#39;9695DFC35FFEB861329B9F1AB04C46397020CE31&#39;</span><span class="p">,</span>
<span class="s">&#39;download_from&#39;</span><span class="p">:</span> <span class="n">stem</span><span class="o">.</span><span class="n">DirPort</span><span class="p">(</span><span class="s">&#39;128.31.0.34&#39;</span><span class="p">,</span> <span class="mi">9131</span><span class="p">),</span>
<span class="s">&#39;print_help&#39;</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">VALID_TYPES</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;server&#39;</span><span class="p">,</span> <span class="s">&#39;extrainfo&#39;</span><span class="p">,</span> <span class="s">&#39;consensus&#39;</span><span class="p">)</span>
<span class="n">HELP_TEXT</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;</span><span class="se">\</span>
<span class="s">Downloads a descriptor through Tor&#39;s ORPort or DirPort.</span>
<span class="s"> -t, --type TYPE descriptor type to download, options are:</span>
<span class="s"> </span><span class="si">%s</span><span class="s"></span>
<span class="s"> -f, --fingerprint FP relay to download the descriptor of</span>
<span class="s"> --orport ADDRESS:PORT ORPort to download from</span>
<span class="s"> --dirport ADDRESS:PORT DirPort to download from</span>
<span class="s"> -h, --help presents this help</span>
<span class="s">&quot;&quot;&quot;</span> <span class="o">%</span> <span class="s">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">VALID_TYPES</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">argv</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Parses our arguments, providing a named tuple with their values.</span>
<span class="sd"> :param list argv: input arguments to be parsed</span>
<span class="sd"> :returns: a **named tuple** with our parsed arguments</span>
<span class="sd"> :raises: **ValueError** if we got an invalid argument</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">args</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">DEFAULT_ARGS</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">recognized_args</span><span class="p">,</span> <span class="n">unrecognized_args</span> <span class="o">=</span> <span class="n">getopt</span><span class="o">.</span><span class="n">getopt</span><span class="p">(</span><span class="n">argv</span><span class="p">,</span> <span class="s">&#39;t:f:h&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;type=&#39;</span><span class="p">,</span> <span class="s">&#39;fingerprint=&#39;</span><span class="p">,</span> <span class="s">&#39;orport=&#39;</span><span class="p">,</span> <span class="s">&#39;dirport=&#39;</span><span class="p">,</span> <span class="s">&#39;help&#39;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">unrecognized_args</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">getopt</span><span class="o">.</span><span class="n">GetoptError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; aren&#39;t recognized arguments&quot;</span> <span class="o">%</span> <span class="s">&quot;&#39;, &#39;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">unrecognized_args</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s"> (for usage provide --help)&#39;</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span>
<span class="k">for</span> <span class="n">opt</span><span class="p">,</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">recognized_args</span><span class="p">:</span>
<span class="k">if</span> <span class="n">opt</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;-t&#39;</span><span class="p">,</span> <span class="s">&#39;--type&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="n">arg</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">VALID_TYPES</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a recognized decriptor type, options are: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="s">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">VALID_TYPES</span><span class="p">)))</span>
<span class="n">args</span><span class="p">[</span><span class="s">&#39;descriptor_type&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">arg</span>
<span class="k">elif</span> <span class="n">opt</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;-f&#39;</span><span class="p">,</span> <span class="s">&#39;--fingerprint&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">arg</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a relay fingerprint&quot;</span> <span class="o">%</span> <span class="n">arg</span><span class="p">)</span>
<span class="n">args</span><span class="p">[</span><span class="s">&#39;fingerprint&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">arg</span>
<span class="k">elif</span> <span class="n">opt</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;--orport&#39;</span><span class="p">,</span> <span class="s">&#39;--dirport&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="s">&#39;:&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; should be of the form &#39;address:port&#39;&quot;</span> <span class="o">%</span> <span class="n">arg</span><span class="p">)</span>
<span class="n">address</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">arg</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">address</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a valid IPv4 address&quot;</span> <span class="o">%</span> <span class="n">address</span><span class="p">)</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">port</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a valid port number&quot;</span> <span class="o">%</span> <span class="n">port</span><span class="p">)</span>
<span class="n">endpoint_class</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">ORPort</span> <span class="k">if</span> <span class="n">opt</span> <span class="o">==</span> <span class="s">&#39;--orport&#39;</span> <span class="k">else</span> <span class="n">stem</span><span class="o">.</span><span class="n">DirPort</span>
<span class="n">args</span><span class="p">[</span><span class="s">&#39;download_from&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">endpoint_class</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">opt</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;-h&#39;</span><span class="p">,</span> <span class="s">&#39;--help&#39;</span><span class="p">):</span>
<span class="n">args</span><span class="p">[</span><span class="s">&#39;print_help&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>
<span class="c"># translates our args dict into a named tuple</span>
<span class="n">Args</span> <span class="o">=</span> <span class="n">collections</span><span class="o">.</span><span class="n">namedtuple</span><span class="p">(</span><span class="s">&#39;Args&#39;</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
<span class="k">return</span> <span class="n">Args</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">parse</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">print_help</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">HELP_TEXT</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39;Downloading </span><span class="si">%s</span><span class="s"> descriptor from </span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">...</span><span class="se">\n</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">descriptor_type</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">download_from</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">download_from</span><span class="o">.</span><span class="n">port</span><span class="p">))</span>
<span class="n">desc</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">descriptor_type</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;server&#39;</span><span class="p">,</span> <span class="s">&#39;extrainfo&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">descriptor_type</span> <span class="o">==</span> <span class="s">&#39;server&#39;</span><span class="p">:</span>
<span class="n">download_func</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">remote</span><span class="o">.</span><span class="n">get_server_descriptors</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">download_func</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">remote</span><span class="o">.</span><span class="n">get_extrainfo_descriptors</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">download_func</span><span class="p">(</span>
<span class="n">fingerprints</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">],</span>
<span class="n">endpoints</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="o">.</span><span class="n">download_from</span><span class="p">],</span>
<span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">args</span><span class="o">.</span><span class="n">descriptor_type</span> <span class="o">==</span> <span class="s">&#39;consensus&#39;</span><span class="p">:</span>
<span class="k">for</span> <span class="n">consensus_desc</span> <span class="ow">in</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">remote</span><span class="o">.</span><span class="n">get_consensus</span><span class="p">(</span><span class="n">endpoints</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="o">.</span><span class="n">download_from</span><span class="p">]):</span>
<span class="k">if</span> <span class="n">consensus_desc</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">==</span> <span class="n">args</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">:</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">consensus_desc</span>
<span class="k">break</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">desc</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39;Unable to find a descriptor for </span><span class="si">%s</span><span class="s"> in the consensus&#39;</span> <span class="o">%</span> <span class="n">args</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</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">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; is not a recognized descriptor type, options are: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">descriptor_type</span><span class="p">,</span> <span class="s">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">VALID_TYPES</span><span class="p">)))</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">desc</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<div class="highlight-python"><pre>% python download_descriptor.py --type consensus --dirport 128.31.0.34:9131
Downloading consensus descriptor from 128.31.0.34:9131...
r moria1 lpXfw1/+uGEym58asExGOXAgzjE IpcU7dolas8+Q+oAzwgvZIWx7PA 2018-05-23 02:41:25 128.31.0.34 9101 9131
s Authority Fast Running Stable V2Dir Valid
v Tor 0.3.3.5-rc-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=20 Unmeasured=1
p reject 1-65535</pre>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

165
docs/exit_used.html Normal file
View File

@ -0,0 +1,165 @@
<!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>Determine The Exit You&#39;re Using &mdash; 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>Determine The Exit You&#39;re Using</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="../over_the_river.html">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="determine-the-exit-you-re-using">
<h1>Determine The Exit You're Using<a class="headerlink" href="#determine-the-exit-you-re-using" title="Permalink to this headline"></a></h1>
<a class="reference external image-reference" href="../double_double_toil_and_trouble.html"><img alt="../../_images/back.png" src="../../_images/back.png" /></a>
<p>Lets say you're using Tor and one day you run into something odd. Maybe a
misconfigured relay, or maybe one that's being malicious. How can you figure
out what exit you're using?</p>
<p>Here's a simple script that prints information about the exits used to service
the requests going through Tor...</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">functools</span>
<span class="kn">from</span> <span class="nn">stem</span> <span class="kn">import</span> <span class="n">StreamStatus</span>
<span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">EventType</span><span class="p">,</span> <span class="n">Controller</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Tracking requests for tor exits. Press &#39;enter&#39; to end.&quot;</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;&quot;</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="n">stream_listener</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">stream_event</span><span class="p">,</span> <span class="n">controller</span><span class="p">)</span>
<span class="n">controller</span><span class="o">.</span><span class="n">add_event_listener</span><span class="p">(</span><span class="n">stream_listener</span><span class="p">,</span> <span class="n">EventType</span><span class="o">.</span><span class="n">STREAM</span><span class="p">)</span>
<span class="nb">raw_input</span><span class="p">()</span> <span class="c"># wait for user to press enter</span>
<span class="k">def</span> <span class="nf">stream_event</span><span class="p">(</span><span class="n">controller</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">StreamStatus</span><span class="o">.</span><span class="n">SUCCEEDED</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">circ_id</span><span class="p">:</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_circuit</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">circ_id</span><span class="p">)</span>
<span class="n">exit_fingerprint</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">path</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">exit_relay</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_network_status</span><span class="p">(</span><span class="n">exit_fingerprint</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Exit relay for our connection to </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">target</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot; address: </span><span class="si">%s</span><span class="s">:</span><span class="si">%i</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">exit_relay</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">exit_relay</span><span class="o">.</span><span class="n">or_port</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot; fingerprint: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">exit_relay</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot; nickname: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">exit_relay</span><span class="o">.</span><span class="n">nickname</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot; locale: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;ip-to-country/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">exit_relay</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="s">&#39;unknown&#39;</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>Now if you make a request over Tor...</p>
<div class="highlight-python"><pre>% curl --socks4a 127.0.0.1:9050 google.com
&lt;HTML&gt;&lt;HEAD&gt;&lt;meta http-equiv="content-type" content="text/html;charset=utf-8"&gt;
&lt;TITLE&gt;301 Moved&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt;
&lt;H1&gt;301 Moved&lt;/H1&gt;
The document has moved
&lt;A HREF="http://www.google.com/"&gt;here&lt;/A&gt;.
&lt;/BODY&gt;&lt;/HTML&gt;</pre>
</div>
<p>... this script will tell you about the exit...</p>
<div class="highlight-python"><pre>% python exit_used.py
Tracking requests for tor exits. Press 'enter' to end.
Exit relay for our connection to 64.15.112.44:80
address: 31.172.30.2:443
fingerprint: A59E1E7C7EAEE083D756EE1FF6EC31CA3D8651D7
nickname: chaoscomputerclub19
locale: unknown</pre>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

146
docs/list_circuits.html Normal file
View File

@ -0,0 +1,146 @@
<!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>List Circuits &mdash; 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>List Circuits</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="../over_the_river.html">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="list-circuits">
<h1>List Circuits<a class="headerlink" href="#list-circuits" title="Permalink to this headline"></a></h1>
<a class="reference external image-reference" href="../double_double_toil_and_trouble.html"><img alt="../../_images/back.png" src="../../_images/back.png" /></a>
<p>Tor creates new circuits and tears down old ones on your behalf, so how can you
get information about circuits Tor currently has available?</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">stem</span> <span class="kn">import</span> <span class="n">CircStatus</span>
<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="k">for</span> <span class="n">circ</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">controller</span><span class="o">.</span><span class="n">get_circuits</span><span class="p">()):</span>
<span class="k">if</span> <span class="n">circ</span><span class="o">.</span><span class="n">status</span> <span class="o">!=</span> <span class="n">CircStatus</span><span class="o">.</span><span class="n">BUILT</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Circuit </span><span class="si">%s</span><span class="s"> (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">circ</span><span class="o">.</span><span class="n">purpose</span><span class="p">))</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">entry</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">path</span><span class="p">):</span>
<span class="n">div</span> <span class="o">=</span> <span class="s">&#39;+&#39;</span> <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">path</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="k">else</span> <span class="s">&#39;|&#39;</span>
<span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span> <span class="o">=</span> <span class="n">entry</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_network_status</span><span class="p">(</span><span class="n">fingerprint</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="n">address</span> <span class="o">=</span> <span class="n">desc</span><span class="o">.</span><span class="n">address</span> <span class="k">if</span> <span class="n">desc</span> <span class="k">else</span> <span class="s">&#39;unknown&#39;</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot; </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="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">div</span><span class="p">,</span> <span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span><span class="p">,</span> <span class="n">address</span><span class="p">))</span>
</pre></div>
</div>
<div class="highlight-python"><pre>% python list_circuits.py
Circuit 4 (GENERAL)
|- B1FA7D51B8B6F0CB585D944F450E7C06EDE7E44C (ByTORAndTheSnowDog, 173.209.180.61)
|- 0DD9935C5E939CFA1E07B8DDA6D91C1A2A9D9338 (afo02, 87.238.194.176)
+- DB3B1CFBD3E4D97B84B548ADD5B9A31451EEC4CC (edwardsnowden3, 109.163.234.10)
Circuit 6 (GENERAL)
|- B1FA7D51B8B6F0CB585D944F450E7C06EDE7E44C (ByTORAndTheSnowDog, 173.209.180.61)
|- EC01CB4766BADC1611678555CE793F2A7EB2D723 (sprockets, 46.165.197.96)
+- 9EA317EECA56BDF30CAEB208A253FB456EDAB1A0 (bolobolo1, 96.47.226.20)
Circuit 10 (GENERAL)
|- B1FA7D51B8B6F0CB585D944F450E7C06EDE7E44C (ByTORAndTheSnowDog, 173.209.180.61)
|- 00C2C2A16AEDB51D5E5FB7D6168FC66B343D822F (ph3x, 86.59.119.83)
+- 65242C91BFF30F165DA4D132C81A9EBA94B71D62 (torexit16, 176.67.169.171)</pre>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

139
docs/outdated_relays.html Normal file
View File

@ -0,0 +1,139 @@
<!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>List Outdated Relays &mdash; 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>List Outdated Relays</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="../over_the_river.html">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="list-outdated-relays">
<h1>List Outdated Relays<a class="headerlink" href="#list-outdated-relays" title="Permalink to this headline"></a></h1>
<a class="reference external image-reference" href="../double_double_toil_and_trouble.html"><img alt="../../_images/back.png" src="../../_images/back.png" /></a>
<p>Time marches on. Tor makes new releases, and at some point needs to drop
support for old ones. Below is the script we used on <a class="reference external" href="https://trac.torproject.org/9476">ticket 9476</a> to reach out
to relay operators that needed to upgrade.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">stem.descriptor.remote</span> <span class="kn">import</span> <span class="n">DescriptorDownloader</span>
<span class="kn">from</span> <span class="nn">stem.version</span> <span class="kn">import</span> <span class="n">Version</span>
<span class="n">downloader</span> <span class="o">=</span> <span class="n">DescriptorDownloader</span><span class="p">()</span>
<span class="n">count</span><span class="p">,</span> <span class="n">with_contact</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;Checking for outdated relays...&quot;</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">downloader</span><span class="o">.</span><span class="n">get_server_descriptors</span><span class="p">():</span>
<span class="k">if</span> <span class="n">desc</span><span class="o">.</span><span class="n">tor_version</span> <span class="o">&lt;</span> <span class="n">Version</span><span class="p">(</span><span class="s">&#39;0.2.3.0&#39;</span><span class="p">):</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">desc</span><span class="o">.</span><span class="n">contact</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39; </span><span class="si">%-15s</span><span class="s"> </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">desc</span><span class="o">.</span><span class="n">tor_version</span><span class="p">,</span> <span class="n">desc</span><span class="o">.</span><span class="n">contact</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&quot;utf-8&quot;</span><span class="p">,</span> <span class="s">&quot;replace&quot;</span><span class="p">)))</span>
<span class="n">with_contact</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%i</span><span class="s"> outdated relays found, </span><span class="si">%i</span><span class="s"> had contact information&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">with_contact</span><span class="p">))</span>
</pre></div>
</div>
<div class="highlight-python"><pre>% python outdated_relays.py
Checking for outdated relays...
0.2.2.39 Random Person admin@gtr-10.de
0.2.2.36 dobrovich_psckaal at vietrievus dot ok
0.2.2.39 anonymous6 anonymous@mailinator.com
0.2.2.39 anonymous12 anonymous@mailinator.com
...
316 outdated relays found, 120 had contact information</pre>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

362
docs/over_the_river.html Normal file
View File

@ -0,0 +1,362 @@
<!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 &mdash; 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">&#39;/&#39;</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">&quot;&lt;h1&gt;Hi Grandma!&lt;/h1&gt;&quot;</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39; * Connecting to tor&#39;</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&#39;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">&#39;DataDirectory&#39;</span><span class="p">,</span> <span class="s">&#39;/tmp&#39;</span><span class="p">),</span> <span class="s">&#39;hello_world&#39;</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">&quot; * Creating our hidden service in </span><span class="si">%s</span><span class="s">&quot;</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">&quot; * Our service is available at </span><span class="si">%s</span><span class="s">, press ctrl+c to quit&quot;</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">&quot; * Unable to determine our service&#39;s hostname, probably due to being unable to read the hidden service directory&quot;</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&#39;t*</span>
<span class="c"># want to delete the hidden service directory if you&#39;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">&quot; * Shutting down our hidden service&quot;</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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span><span class="n">controller</span><span class="o">.</span><span class="n">authenticate</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </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">&#39;bob&#39;</span><span class="p">:</span> <span class="bp">None</span><span class="p">,</span> <span class="s">&#39;alice&#39;</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </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">(&#39;l3lnorirzn7hrjnw&#39;, {&#39;alice&#39;: &#39;I6AMKiay+UkM5MfrvdnF2A&#39;, &#39;bob&#39;: &#39;VLsbrSGyrb5JYEvZmQ3tMg&#39;})</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">&gt;&gt;&gt; </span><span class="n">controller</span><span class="o">.</span><span class="n">set_conf</span><span class="p">(</span><span class="s">&#39;HidServAuth&#39;</span><span class="p">,</span> <span class="s">&#39;l3lnorirzn7hrjnw.onion I6AMKiay+UkM5MfrvdnF2A&#39;</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">&#39;/&#39;</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">&quot;&lt;h1&gt;Hi Grandma!&lt;/h1&gt;&quot;</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39; * Connecting to tor&#39;</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">&quot; * Our service is available at </span><span class="si">%s</span><span class="s">.onion, press ctrl+c to quit&quot;</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">&quot; * Shutting down our hidden service&quot;</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">&#39;~/my_service_key&#39;</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">&quot;Started a new hidden service with the address of </span><span class="si">%s</span><span class="s">.onion&quot;</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">&#39;w&#39;</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">&#39;</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&#39;</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">&#39;:&#39;</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">&quot;Resumed </span><span class="si">%s</span><span class="s">.onion&quot;</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">&#39;press any key to shut the service down...&#39;</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&#39;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">&#39;3g2upl4pq6kufc4m&#39;</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">&#39;3g2upl4pq6kufc4m&#39;</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&quot;DuckDuckGo&#39;s introduction points are...</span><span class="se">\n</span><span class="s">&quot;</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">&#39; </span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s"> =&gt; </span><span class="si">%s</span><span class="s">&#39;</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 =&gt; vsrn2pcmw3ogmf4j7tjqxzmviucdk4ki
104.131.106.181:9001 =&gt; gcl2kpqx5qnkpgxjf6x7ulqncoqj7ghh
188.166.58.218:443 =&gt; jeymnbhs2d6l2oib7jjvweavg45m6gju</pre>
</div>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

276
docs/relay_connections.html Normal file
View File

@ -0,0 +1,276 @@
<!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>Connection Summary &mdash; 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>Connection Summary</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="../over_the_river.html">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="connection-summary">
<h1>Connection Summary<a class="headerlink" href="#connection-summary" title="Permalink to this headline"></a></h1>
<a class="reference external image-reference" href="../double_double_toil_and_trouble.html"><img alt="../../_images/back.png" src="../../_images/back.png" /></a>
<p>The following provides a summary of your relay's inbound and outbound
connections. Couple important notes...</p>
<blockquote>
<div><ul>
<li><p class="first">To use this you must set <strong>DisableDebuggerAttachment 0</strong> in your torrc.
Otherwise connection information will be unavailable.</p>
</li>
<li><p class="first"><strong>Be careful about the data you look at.</strong> Inspection of client and exit
traffic especially is wiretapping and not only unethical but likely
illegal.</p>
<p>That said, a general overview like this should be fine.</p>
</li>
</ul>
</div></blockquote>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">argparse</span>
<span class="kn">import</span> <span class="nn">collections</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">stem.connection</span>
<span class="kn">import</span> <span class="nn">stem.util.system</span>
<span class="kn">import</span> <span class="nn">stem.util.str_tools</span>
<span class="kn">from</span> <span class="nn">stem.control</span> <span class="kn">import</span> <span class="n">Listener</span>
<span class="kn">from</span> <span class="nn">stem.util.connection</span> <span class="kn">import</span> <span class="n">get_connections</span><span class="p">,</span> <span class="n">port_usage</span><span class="p">,</span> <span class="n">is_valid_ipv4_address</span>
<span class="n">HEADER_LINE</span> <span class="o">=</span> <span class="s">&quot; {version} uptime: {uptime} flags: {flags}</span><span class="se">\n</span><span class="s">&quot;</span>
<span class="n">DIV</span> <span class="o">=</span> <span class="s">&#39;+</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">+&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="s">&#39;-&#39;</span> <span class="o">*</span> <span class="mi">30</span><span class="p">,</span> <span class="s">&#39;-&#39;</span> <span class="o">*</span> <span class="mi">6</span><span class="p">,</span> <span class="s">&#39;-&#39;</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span>
<span class="n">COLUMN</span> <span class="o">=</span> <span class="s">&#39;| </span><span class="si">%-28s</span><span class="s"> | </span><span class="si">%4s</span><span class="s"> | </span><span class="si">%4s</span><span class="s"> |&#39;</span>
<span class="n">INBOUND_ORPORT</span> <span class="o">=</span> <span class="s">&#39;Inbound to our ORPort&#39;</span>
<span class="n">INBOUND_DIRPORT</span> <span class="o">=</span> <span class="s">&#39;Inbound to our DirPort&#39;</span>
<span class="n">INBOUND_CONTROLPORT</span> <span class="o">=</span> <span class="s">&#39;Inbound to our ControlPort&#39;</span>
<span class="n">OUTBOUND_ORPORT</span> <span class="o">=</span> <span class="s">&#39;Outbound to a relay&#39;</span>
<span class="n">OUTBOUND_EXIT</span> <span class="o">=</span> <span class="s">&#39;Outbound exit traffic&#39;</span>
<span class="n">OUTBOUND_UNKNOWN</span> <span class="o">=</span> <span class="s">&#39;Outbound uncategorized&#39;</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;--ctrlport&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;default: 9051 or 9151&quot;</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">&quot;--resolver&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;default: autodetected&quot;</span><span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="n">control_port</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">ctrlport</span><span class="p">)</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">ctrlport</span> <span class="k">else</span> <span class="s">&#39;default&#39;</span>
<span class="n">controller</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">control_port</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">control_port</span><span class="p">))</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">controller</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">desc</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_network_status</span><span class="p">(</span><span class="n">default</span> <span class="o">=</span> <span class="bp">None</span><span class="p">)</span>
<span class="n">pid</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_pid</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">HEADER_LINE</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">version</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">controller</span><span class="o">.</span><span class="n">get_version</span><span class="p">())</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">],</span>
<span class="n">uptime</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">short_time_label</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">start_time</span><span class="p">(</span><span class="n">pid</span><span class="p">)),</span>
<span class="n">flags</span> <span class="o">=</span> <span class="s">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">desc</span><span class="o">.</span><span class="n">flags</span> <span class="k">if</span> <span class="n">desc</span> <span class="k">else</span> <span class="p">[</span><span class="s">&#39;none&#39;</span><span class="p">]),</span>
<span class="p">))</span>
<span class="n">policy</span> <span class="o">=</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_exit_policy</span><span class="p">()</span>
<span class="n">relays</span> <span class="o">=</span> <span class="p">{}</span> <span class="c"># address =&gt; [orports...]</span>
<span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_network_statuses</span><span class="p">():</span>
<span class="n">relays</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">desc</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">desc</span><span class="o">.</span><span class="n">or_port</span><span class="p">)</span>
<span class="c"># categorize our connections</span>
<span class="n">categories</span> <span class="o">=</span> <span class="n">collections</span><span class="o">.</span><span class="n">OrderedDict</span><span class="p">((</span>
<span class="p">(</span><span class="n">INBOUND_ORPORT</span><span class="p">,</span> <span class="p">[]),</span>
<span class="p">(</span><span class="n">INBOUND_DIRPORT</span><span class="p">,</span> <span class="p">[]),</span>
<span class="p">(</span><span class="n">INBOUND_CONTROLPORT</span><span class="p">,</span> <span class="p">[]),</span>
<span class="p">(</span><span class="n">OUTBOUND_ORPORT</span><span class="p">,</span> <span class="p">[]),</span>
<span class="p">(</span><span class="n">OUTBOUND_EXIT</span><span class="p">,</span> <span class="p">[]),</span>
<span class="p">(</span><span class="n">OUTBOUND_UNKNOWN</span><span class="p">,</span> <span class="p">[]),</span>
<span class="p">))</span>
<span class="n">exit_connections</span> <span class="o">=</span> <span class="p">{}</span> <span class="c"># port =&gt; [connections]</span>
<span class="k">for</span> <span class="n">conn</span> <span class="ow">in</span> <span class="n">get_connections</span><span class="p">(</span><span class="n">resolver</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">resolver</span><span class="p">,</span> <span class="n">process_pid</span> <span class="o">=</span> <span class="n">pid</span><span class="p">):</span>
<span class="k">if</span> <span class="n">conn</span><span class="o">.</span><span class="n">protocol</span> <span class="o">==</span> <span class="s">&#39;udp&#39;</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="n">conn</span><span class="o">.</span><span class="n">local_port</span> <span class="ow">in</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_ports</span><span class="p">(</span><span class="n">Listener</span><span class="o">.</span><span class="n">OR</span><span class="p">,</span> <span class="p">[]):</span>
<span class="n">categories</span><span class="p">[</span><span class="n">INBOUND_ORPORT</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">conn</span><span class="o">.</span><span class="n">local_port</span> <span class="ow">in</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_ports</span><span class="p">(</span><span class="n">Listener</span><span class="o">.</span><span class="n">DIR</span><span class="p">,</span> <span class="p">[]):</span>
<span class="n">categories</span><span class="p">[</span><span class="n">INBOUND_DIRPORT</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">conn</span><span class="o">.</span><span class="n">local_port</span> <span class="ow">in</span> <span class="n">controller</span><span class="o">.</span><span class="n">get_ports</span><span class="p">(</span><span class="n">Listener</span><span class="o">.</span><span class="n">CONTROL</span><span class="p">,</span> <span class="p">[]):</span>
<span class="n">categories</span><span class="p">[</span><span class="n">INBOUND_CONTROLPORT</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">conn</span><span class="o">.</span><span class="n">remote_port</span> <span class="ow">in</span> <span class="n">relays</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">remote_address</span><span class="p">,</span> <span class="p">[]):</span>
<span class="n">categories</span><span class="p">[</span><span class="n">OUTBOUND_ORPORT</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">policy</span><span class="o">.</span><span class="n">can_exit_to</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">remote_address</span><span class="p">,</span> <span class="n">conn</span><span class="o">.</span><span class="n">remote_port</span><span class="p">):</span>
<span class="n">categories</span><span class="p">[</span><span class="n">OUTBOUND_EXIT</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="n">exit_connections</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">remote_port</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">categories</span><span class="p">[</span><span class="n">OUTBOUND_UNKNOWN</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">COLUMN</span> <span class="o">%</span> <span class="p">(</span><span class="s">&#39;Type&#39;</span><span class="p">,</span> <span class="s">&#39;IPv4&#39;</span><span class="p">,</span> <span class="s">&#39;IPv6&#39;</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="n">total_ipv4</span><span class="p">,</span> <span class="n">total_ipv6</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">label</span><span class="p">,</span> <span class="n">connections</span> <span class="ow">in</span> <span class="n">categories</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">connections</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">continue</span>
<span class="n">ipv4_count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">([</span><span class="n">conn</span> <span class="k">for</span> <span class="n">conn</span> <span class="ow">in</span> <span class="n">connections</span> <span class="k">if</span> <span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">remote_address</span><span class="p">)])</span>
<span class="n">ipv6_count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">connections</span><span class="p">)</span> <span class="o">-</span> <span class="n">ipv4_count</span>
<span class="n">total_ipv4</span><span class="p">,</span> <span class="n">total_ipv6</span> <span class="o">=</span> <span class="n">total_ipv4</span> <span class="o">+</span> <span class="n">ipv4_count</span><span class="p">,</span> <span class="n">total_ipv6</span> <span class="o">+</span> <span class="n">ipv6_count</span>
<span class="k">print</span><span class="p">(</span><span class="n">COLUMN</span> <span class="o">%</span> <span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">ipv4_count</span><span class="p">,</span> <span class="n">ipv6_count</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">COLUMN</span> <span class="o">%</span> <span class="p">(</span><span class="s">&#39;Total&#39;</span><span class="p">,</span> <span class="n">total_ipv4</span><span class="p">,</span> <span class="n">total_ipv6</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">exit_connections</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">COLUMN</span> <span class="o">%</span> <span class="p">(</span><span class="s">&#39;Exit Port&#39;</span><span class="p">,</span> <span class="s">&#39;IPv4&#39;</span><span class="p">,</span> <span class="s">&#39;IPv6&#39;</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="n">total_ipv4</span><span class="p">,</span> <span class="n">total_ipv6</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">port</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">exit_connections</span><span class="p">):</span>
<span class="n">connections</span> <span class="o">=</span> <span class="n">exit_connections</span><span class="p">[</span><span class="n">port</span><span class="p">]</span>
<span class="n">ipv4_count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">([</span><span class="n">conn</span> <span class="k">for</span> <span class="n">conn</span> <span class="ow">in</span> <span class="n">connections</span> <span class="k">if</span> <span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">remote_address</span><span class="p">)])</span>
<span class="n">ipv6_count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">connections</span><span class="p">)</span> <span class="o">-</span> <span class="n">ipv4_count</span>
<span class="n">total_ipv4</span><span class="p">,</span> <span class="n">total_ipv6</span> <span class="o">=</span> <span class="n">total_ipv4</span> <span class="o">+</span> <span class="n">ipv4_count</span><span class="p">,</span> <span class="n">total_ipv6</span> <span class="o">+</span> <span class="n">ipv6_count</span>
<span class="n">usage</span> <span class="o">=</span> <span class="n">port_usage</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
<span class="n">label</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s"> (</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">port</span><span class="p">,</span> <span class="n">usage</span><span class="p">)</span> <span class="k">if</span> <span class="n">usage</span> <span class="k">else</span> <span class="n">port</span>
<span class="k">print</span><span class="p">(</span><span class="n">COLUMN</span> <span class="o">%</span> <span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">ipv4_count</span><span class="p">,</span> <span class="n">ipv6_count</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">COLUMN</span> <span class="o">%</span> <span class="p">(</span><span class="s">&#39;Total&#39;</span><span class="p">,</span> <span class="n">total_ipv4</span><span class="p">,</span> <span class="n">total_ipv6</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">DIV</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<div class="highlight-python"><pre>% relay_connections.py --ctrlport 29051
0.3.2.0-alpha-dev uptime: 01:20:44 flags: none
+------------------------------+------+------+
| Type | IPv4 | IPv6 |
+------------------------------+------+------+
| Inbound to our ORPort | 2400 | 3 |
| Inbound to our DirPort | 12 | 0 |
| Inbound to our ControlPort | 2 | 0 |
| Outbound to a relay | 324 | 0 |
| Outbound exit traffic | 3 | 0 |
+------------------------------+------+------+
| Total | 2741 | 3 |
+------------------------------+------+------+
+------------------------------+------+------+
| Exit Port | IPv4 | IPv6 |
+------------------------------+------+------+
| 443 (HTTPS) | 1 | 0 |
| 8443 (PCsync HTTPS) | 1 | 0 |
| 54682 | 1 | 0 |
+------------------------------+------+------+
| Total | 3 | 0 |
+------------------------------+------+------+</pre>
</div>
</div>
</div>
<div class="bottomnav">
</div>
<div class="footer">
</div>
</body>
</html>

45
pyproject.toml Normal file
View File

@ -0,0 +1,45 @@
[project]
name = "stem_examples"
version = "2023.12"
description = "examples of using stem"
authors = [{ name = "emdee", email = "Ingvar@gitgub.com" } ]
requires-python = ">=3.6"
dependencies = [
'stem',
]
keywords = ["stem", "python3", "tor"]
classifiers = [
"License :: OSI Approved",
"Operating System :: POSIX :: BSD :: FreeBSD",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
]
dynamic = ["version", "readme", ] # cannot be dynamic ['license']
scripts = { exclude_badExits = "stem_examples.exclude_badExits:iMain" }
#[project.license]
#file = "LICENSE.md"
[project.urls]
repository = "https://git.plastiras.org/emdee/stem_examples"
[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools.dynamic]
version = {attr = "stem_examples.__version__"}
readme = {file = ["README.md", "exclude_badExits.md"]}
[tool.setuptools]
packages = ["stem_examples"]
#[tool.setuptools.packages.find]
#where = "src"

67
setup.cfg Normal file
View File

@ -0,0 +1,67 @@
[metadata]
classifiers =
License :: OSI Approved
License :: OSI Approved :: BSD 1-clause
Intended Audience :: Web Developers
Operating System :: Microsoft :: Windows
Operating System :: POSIX :: BSD :: FreeBSD
Operating System :: POSIX :: Linux
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: Implementation :: CPython
Framework :: AsyncIO
[options]
zip_safe = false
python_requires = ~=3.6
include_package_data = false
install_requires =
qasync
cryptography
rsa
stem
ruamel.yaml
package_dir=
=src
packages=find:
[options.packages.find]
where=src
[options.entry_points]
console_scripts =
phantompy = phantompy.__main__:iMain
exclude_badExits = exclude_badExits:iMain
[easy_install]
zip_ok = false
[flake8]
jobs = 1
max-line-length = 88
ignore =
E111
E114
E128
E225
E261
E302
E305
E402
E501
E502
E541
E701
E702
E704
E722
E741
F508
F541
W503
W601

0
src/stem_examples/__init__.py Normal file → Executable file
View File

View File

@ -31,7 +31,7 @@ def download_descriptors(fingerprint):
) )
if __name__ == '__main__': if __name__ == '__main__':
set_socks_proxy() set_socks_proxy()
fingerprint = input("What relay fingerprint would you like to validate?\n") fingerprint = input("What relay fingerprint would you like to validate?\n")
print('') # blank line print('') # blank line

27
src/stem_examples/compare_flags.py Normal file → Executable file
View File

@ -1,4 +1,5 @@
# -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- # -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
#
import sys import sys
import collections import collections
@ -14,36 +15,36 @@ def iMain():
downloader = stem.descriptor.remote.DescriptorDownloader( downloader = stem.descriptor.remote.DescriptorDownloader(
document_handler = stem.descriptor.DocumentHandler.DOCUMENT, document_handler = stem.descriptor.DocumentHandler.DOCUMENT,
) )
# An ordered dictionary ensures queries are finished in the order they were # An ordered dictionary ensures queries are finished in the order they were
# added. # added.
queries = collections.OrderedDict() queries = collections.OrderedDict()
for name, authority in stem.directory.Authority.from_cache().items(): for name, authority in stem.directory.Authority.from_cache().items():
if authority.v3ident is None: if authority.v3ident is None:
continue # authority doesn't vote if it lacks a v3ident continue # authority doesn't vote if it lacks a v3ident
queries[name] = downloader.get_vote(authority) queries[name] = downloader.get_vote(authority)
# Wait for the votes to finish being downloaded, this produces a dictionary of # Wait for the votes to finish being downloaded, this produces a dictionary of
# authority nicknames to their vote. # authority nicknames to their vote.
votes = dict((name, query.run()[0]) for (name, query) in queries.items()) votes = dict((name, query.run()[0]) for (name, query) in queries.items())
# Get a superset of all the fingerprints in all the votes. # Get a superset of all the fingerprints in all the votes.
all_fingerprints = set() all_fingerprints = set()
for vote in votes.values(): for vote in votes.values():
all_fingerprints.update(vote.routers.keys()) all_fingerprints.update(vote.routers.keys())
# Finally, compare moria1's votes to maatuska's votes. # Finally, compare moria1's votes to maatuska's votes.
for fingerprint in all_fingerprints: for fingerprint in all_fingerprints:
moria1_vote = votes['moria1'].routers.get(fingerprint) moria1_vote = votes['moria1'].routers.get(fingerprint)
maatuska_vote = votes['maatuska'].routers.get(fingerprint) maatuska_vote = votes['maatuska'].routers.get(fingerprint)
if not moria1_vote and not maatuska_vote: if not moria1_vote and not maatuska_vote:
print("both moria1 and maatuska haven't voted about %s" % fingerprint) print("both moria1 and maatuska haven't voted about %s" % fingerprint)
elif not moria1_vote: elif not moria1_vote:
@ -54,7 +55,7 @@ def iMain():
print("moria1 has the Running flag but maatuska doesn't: %s" % fingerprint) print("moria1 has the Running flag but maatuska doesn't: %s" % fingerprint)
elif 'Running' in maatuska_vote.flags and 'Running' not in moria1_vote.flags: elif 'Running' in maatuska_vote.flags and 'Running' not in moria1_vote.flags:
print("maatuska has the Running flag but moria1 doesn't: %s" % fingerprint) print("maatuska has the Running flag but moria1 doesn't: %s" % fingerprint)
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -1,5 +1,12 @@
# -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- # -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
# https://stem.torproject.org/tutorials/examples/exit_used.html # https://stem.torproject.org/tutorials/examples/exit_used.html
__doc__ = """Determine The Exit You're Using
Lets say you're using Tor and one day you run into something odd. Maybe a
misconfigured relay, or maybe one that's being malicious.
How can you figure out what exit you're using?
"""
import functools import functools
import sys import sys
@ -25,7 +32,7 @@ def stream_event(controller, event):
from tor_controller import get_controller from tor_controller import get_controller
def main(): def iMain():
print("Please wait for requests for tor exits. Press 'enter' to end.") print("Please wait for requests for tor exits. Press 'enter' to end.")
print("") print("")
if os.path.exists('/run/tor/control'): if os.path.exists('/run/tor/control'):
@ -38,9 +45,9 @@ def main():
stream_listener = functools.partial(stream_event, controller) stream_listener = functools.partial(stream_event, controller)
controller.add_event_listener(stream_listener, EventType.STREAM) controller.add_event_listener(stream_listener, EventType.STREAM)
if __name__ == '__main__':
iMain()
print('Press Enter') print('Press Enter')
input() # wait for user to press enter input() # wait for user to press enter
if __name__ == '__main__':
main()

41
src/stem_examples/introduction_points.py Normal file → Executable file
View File

@ -1,13 +1,36 @@
#!/usr/local/bin/python3.sh
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
# http://vt5hknv6sblkgf22.onion/tutorials/over_the_river.html # https://stem.torproject.org/tutorials/over_the_river.html
__doc__ = """
Hidden services give you a way of providing a service without exposing your address. These services are only accessible through Tor or Tor2web, and useful for a surprising number of things...
Hosting an anonymized site. This is usually the first thing that comes to mind, and something we'll demonstrate in a sec.
Providing an endpoint Tor users can reach without exiting the Tor network. This eliminates the risk of an unreliable or malicious exit getting in the way. Great examples of this are Facebook (facebookcorewwwi.onion) and DuckDuckGo (3g2upl4pq6kufc4m.onion).
Personal services. For instance you can host your home SSH server as a hidden service to prevent eavesdroppers from knowing where you live while traveling abroad.
Tor2web provides a quick and easy way of seeing if your hidden service is working. To use it simply replace the .onion of your address with .tor2web.org...
This script tests if you can reach a hidden service, passed as an onion address
as an argument. If no argument is given, 3 common onion sites are tested:
Facebook, DuckDuckGo, and .
"""
import sys import sys
import os import os
import getpass import getpass
from stem.control import Controller from stem.control import Controller
from tor_controller import get_controller from tor_controller import get_controller
lKNOWN_ONIONS = [
'facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd', # facebook
'duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad', # ddg
'zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad', # hks
]
def iMain(lArgs=None): def iMain(lArgs=None):
if lArgs is None: if lArgs is None:
lArgs = sys.argv[1:] lArgs = sys.argv[1:]
@ -16,10 +39,10 @@ def iMain(lArgs=None):
controller = get_controller(unix='/run/tor/control') controller = get_controller(unix='/run/tor/control')
else: else:
controller = get_controller(port=9051) controller = get_controller(port=9051)
password = os.environ.get('TOR_CONTROLLER_PASSWORD') password = os.environ.get('TOR_CONTROLLER_PASSWORD')
controller.authenticate(password) controller.authenticate(password)
for elt in lArgs: for elt in lArgs:
desc = controller.get_hidden_service_descriptor(elt, await_result=True, timeout=None) desc = controller.get_hidden_service_descriptor(elt, await_result=True, timeout=None)
print(f"{desc} get_hidden_service_descriptor\n") print(f"{desc} get_hidden_service_descriptor\n")
@ -28,28 +51,22 @@ def iMain(lArgs=None):
print(f"{elt} NO introduction points\n") print(f"{elt} NO introduction points\n")
continue continue
print(f"{elt} introduction points are...\n") print(f"{elt} introduction points are...\n")
for introduction_point in l: for introduction_point in l:
print(' %s:%s => %s' % (introduction_point.address, print(' %s:%s => %s' % (introduction_point.address,
introduction_point.port, introduction_point.port,
introduction_point.identifier)) introduction_point.identifier))
except Exception as e: except Exception as e:
print(e) print(e)
finally: finally:
del controller del controller
return 0 return 0
lKNOWN_ONIONS = [
'facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd', # facebook
'duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad', # ddg
'zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad', # hks
]
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) <= 1: if len(sys.argv) <= 1:
lArgs = lKNOWN_ONIONS lArgs = lKNOWN_ONIONS
else: else:
lArgs = sys.argv[1:] lArgs = sys.argv[1:]
sys.exit(iMain()) sys.exit(iMain())

View File

@ -13,31 +13,31 @@ def iMain():
controller = get_controller(unix='/run/tor/control') controller = get_controller(unix='/run/tor/control')
else: else:
controller = get_controller(port=9051) controller = get_controller(port=9051)
password = os.environ.get('TOR_CONTROLLER_PASSWORD') password = os.environ.get('TOR_CONTROLLER_PASSWORD')
try: try:
controller.authenticate(password) controller.authenticate(password)
for circ in sorted(controller.get_circuits()): for circ in sorted(controller.get_circuits()):
if circ.status != CircStatus.BUILT: if circ.status != CircStatus.BUILT:
continue continue
print("") print("")
print("Circuit %s (%s)" % (circ.id, circ.purpose)) print("Circuit %s (%s)" % (circ.id, circ.purpose))
for i, entry in enumerate(circ.path): for i, entry in enumerate(circ.path):
div = '+' if (i == len(circ.path) - 1) else '|' div = '+' if (i == len(circ.path) - 1) else '|'
fingerprint, nickname = entry fingerprint, nickname = entry
desc = controller.get_network_status(fingerprint, None) desc = controller.get_network_status(fingerprint, None)
address = desc.address if desc else 'unknown' address = desc.address if desc else 'unknown'
print(" %s- %s (%s, %s)" % (div, fingerprint, nickname, address)) print(" %s- %s (%s, %s)" % (div, fingerprint, nickname, address))
except Exception as e: except Exception as e:
print(e) print(e)
finally: finally:
del controller del controller
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':

2
src/stem_examples/mappaddress.py Normal file → Executable file
View File

@ -21,7 +21,7 @@ def sMapaddressResolv(target, iPort=9051):
controller = get_controller(unix='/run/tor/control') controller = get_controller(unix='/run/tor/control')
else: else:
controller = get_controller(port=9051) controller = get_controller(port=9051)
password = os.environ.get('TOR_CONTROLLER_PASSWORD') password = os.environ.get('TOR_CONTROLLER_PASSWORD')
controller.authenticate(password) controller.authenticate(password)

6
src/stem_examples/outdated_relays.py Normal file → Executable file
View File

@ -10,15 +10,15 @@ def iMain():
elts = downloader.get_server_descriptors() elts = downloader.get_server_descriptors()
print(f"Checking for outdated relays len server_descriptors={len(list(elts))}...") print(f"Checking for outdated relays len server_descriptors={len(list(elts))}...")
print("") print("")
for desc in elts: for desc in elts:
if desc.tor_version < Version('0.2.3.0'): if desc.tor_version < Version('0.2.3.0'):
count += 1 count += 1
if desc.contact: if desc.contact:
print(' %-15s %s' % (desc.tor_version, desc.contact.decode("utf-8", "replace"))) print(' %-15s %s' % (desc.tor_version, desc.contact.decode("utf-8", "replace")))
with_contact += 1 with_contact += 1
print("") print("")
print("%i outdated relays found, %i had contact information" % (count, with_contact)) print("%i outdated relays found, %i had contact information" % (count, with_contact))
# http://vt5hknv6sblkgf22.onion/tutorials/examples/outdated_relays.htmlhttp://vt5hknv6sblkgf22.onion/tutorials/examples/outdated_relays.html # http://vt5hknv6sblkgf22.onion/tutorials/examples/outdated_relays.htmlhttp://vt5hknv6sblkgf22.onion/tutorials/examples/outdated_relays.html

View File

@ -1,6 +1,15 @@
# -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- # -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
# http://vt5hknv6sblkgf22.onion/tutorials/examples/relay_connections.html # https://stem.torproject.org/tutorials/examples/relay_connections.html
__doc__ = """Connection Summary
The following provides a summary of your relay's inbound and outbound connections.
To use this you must set DisableDebuggerAttachment 0 in your
torrc. Otherwise connection information will be unavailable.
"""
import argparse import argparse
import collections import collections
import os import os
@ -37,7 +46,7 @@ OUTBOUND_UNKNOWN = 'Outbound uncategorized'
def iMain(lArgs=None): def iMain(lArgs=None):
if lArgs is None: if lArgs is None:
lArgs = sys.argv[1:] lArgs = sys.argv[1:]
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--ctrlport", default=9051, type=int, help="default: 9051") parser.add_argument("--ctrlport", default=9051, type=int, help="default: 9051")
parser.add_argument("--resolver", help="default: autodetected") parser.add_argument("--resolver", help="default: autodetected")
@ -49,7 +58,7 @@ def iMain(lArgs=None):
else: else:
controller = get_controller(port=control_port) controller = get_controller(port=control_port)
# controller = stem.connection.connect(control_port = ('127.0.0.1', control_port)) # controller = stem.connection.connect(control_port = ('127.0.0.1', control_port))
password = os.environ.get('TOR_CONTROLLER_PASSWORD') password = os.environ.get('TOR_CONTROLLER_PASSWORD')
controller.authenticate(password) controller.authenticate(password)

View File

@ -1,4 +1,10 @@
#!/usr/bin/python3 -u #!/usr/local/bin/python3.sh -u
# -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
__doc__ = """
A script by adrelanos@riseup.net to check what percentage of boostrapping
tor is at.
"""
## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP <adrelanos@riseup.net> ## Copyright (C) 2012 - 2020 ENCRYPTED SUPPORT LP <adrelanos@riseup.net>
## See the file COPYING for copying conditions. ## See the file COPYING for copying conditions.
@ -43,4 +49,4 @@ def iMain(lArgs=None):
if __name__ == '__main__': if __name__ == '__main__':
sys.exit( iMain()) sys.exit( iMain())

5
src/stem_examples/tor_controller.py Normal file → Executable file
View File

@ -1,4 +1,5 @@
# -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- # -*-mode: python; py-indent-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
import os import os
import sys import sys
import getpass import getpass
@ -29,7 +30,7 @@ def get_controller(password=None, address='127.0.0.1', port=9051, unix='/run/tor
controller = Controller.from_port(address=address, port=port) controller = Controller.from_port(address=address, port=port)
if password is None: if password is None:
print("DBUG: trying TOR_CONTROLLER_PASSWORD") # print("DBUG: trying TOR_CONTROLLER_PASSWORD")
password = os.environ.get('TOR_CONTROLLER_PASSWORD') password = os.environ.get('TOR_CONTROLLER_PASSWORD')
else: else:
# print(f"DBUG: using a password {len(password)}") # print(f"DBUG: using a password {len(password)}")
@ -50,7 +51,7 @@ def get_controller(password=None, address='127.0.0.1', port=9051, unix='/run/tor
controller.authenticate(password) controller.authenticate(password)
except Exception as e: except Exception as e:
print(f"ERROR: {e}") print(f"ERROR: {e}")
return controller return controller

102
stem_examples.txt Normal file
View File

@ -0,0 +1,102 @@
# -*-mode: doctest; tab-width: 0; py-indent-offset: 4; coding: utf-8-unix -*-
== stem_examples tor testing ==
This is a Python doctest file that is executable documentation.
Pass the controller password if needed as an environment variable:
>>> import os
>>> assert os.environ['TOR_CONTROLLER_PASSWORD']
Add our code to the PYTHONPATH
>>> import sys
>>> sys.path.append(os.path.join(os.getcwd(), 'src', 'stem_examples'))
We'll need the settings defined in {{{/usr/local/etc/testforge/testforge.yml}}}
>>> print("yaml", file=sys.stderr)
>>> import yaml
>>> sFacts = open('/usr/local/etc/testforge/testforge.yml').read()
>>> assert sFacts
>>> dFacts = yaml.safe_load(sFacts)
FixMe: use the settings for the ports and directories below.
>>> import os
>>> os.environ['http_proxy'] = 'http://'+dFacts['HTTP_PROXYHOST']+':'+str(dFacts['HTTP_PROXYPORT'])
>>> os.environ['https_proxy'] = 'http://'+dFacts['HTTPS_PROXYHOST']+':'+str(dFacts['HTTPS_PROXYPORT'])
>>> os.environ['socks_proxy'] = 'socks5://'+dFacts['SOCKS_PROXYHOST']+':'+str(dFacts['SOCKS_PROXYPORT'])
### compare_flags Comparing Directory Authority Flags
### introduction_points Introduction Points
>>> print("introduction_points", file=sys.stderr)
>>> import introduction_points
The introduction points are the ways of connecting to hidden services.
We test 3 known hidden services: Facebook, DuckDuckGo and .
>>> lKNOWN_ONIONS = [
... 'facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd', # facebook
... 'duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad', # ddg
... 'zkaan2xfbuxia2wpf7ofnkbz6r5zdbbvxbunvp5g2iebopbfc4iqmbad', # hks
... ]
We wil expect to get back the hidden service version, the descriptor-lifetime
and then the descriptor-signing-key-cert:
>>> introduction_points.iMain(lKNOWN_ONIONS) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
hs-descriptor 3
descriptor-lifetime ...
<BLANKLINE>
### exit_used Determine The Exit You're Using
Lets say you're using Tor and one day you run into something odd. Maybe a
misconfigured relay, or maybe one that's being malicious.
How can you figure out what exit you're using?
>>> print("exit_used", file=sys.stderr)
>>> import exit_used
## relay_connections Connection Summary
>>> print("relay_connections", file=sys.stderr)
>>> import relay_connections
The following provides a summary of your relay's inbound and outbound connections.
You must be root or tor to run this:
relay_connections.iMain(["--ctrlport", "9051"])
## outdated_relays
>>> print("outdated_relays", file=sys.stderr)
>>> import outdated_relays
>>> outdated_relays.iMain() #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
Checking for outdated relays ...
<BLANKLINE>
## tor_bootstrap_check
>>> print("tor_bootstrap_check", file=sys.stderr)
>>> import tor_bootstrap_check
A script by adrelanos@riseup.net to check what percentage of boostrapping
tor is at. This fails under doctest but not from the cmdline
>> tor_bootstrap_check.iMain() #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
NOTICE ...
<BLANKLINE>
control_port = stem.socket.ControlPort(address, port)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/stem/socket.py", line 503, in __init__
self.connect()
File "/usr/local/lib/python3.11/site-packages/stem/socket.py", line 172, in connect
self._socket = self._make_socket()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/stem/socket.py", line 538, in _make_socket
raise stem.SocketError(exc)
stem.SocketError: Socket error: 0x01: General SOCKS server failure