27 Commits

Author SHA1 Message Date
eyedeekay
41dcb29429 temporarily remove WIP libp2p support 2023-07-21 15:24:54 -04:00
eyedeekay
0e2d9a60a4 prepare for official releases 2023-07-21 15:15:29 -04:00
idk
f654f2635b start a libp2p transport 2023-06-25 08:25:19 -04:00
idk
eb11a4ec64 remove gosam from module 2023-01-18 06:53:32 +00:00
idk
e2e443e158 remove gosam from module 2023-01-18 06:53:16 +00:00
idk
c93b68c0ab update sam3 lib 2023-01-16 05:55:07 +00:00
idk
af628a80ce remove bridge attempt for now 2023-01-16 05:54:26 +00:00
idk
c6b30ad4cb remove bridge attempt for now 2023-01-16 05:54:13 +00:00
idk
002fd2f79c bump version 2023-01-07 03:33:41 +00:00
idk
2f2d359ffb change how it expresses addresses on the fly 2023-01-07 03:32:13 +00:00
idk
59c4ed7e73 Add DialContext 2022-12-29 20:56:37 +00:00
idk
dc495c94f6 Add datagram sessions 2022-12-29 20:03:42 +00:00
idk
64cb1842d0 update EXAMPLE.html 2022-08-29 01:01:01 -04:00
idk
55f43b8382 update DOCS.html 2022-08-29 01:00:58 -04:00
idk
1c866297b5 update DESC.html 2022-08-29 01:00:55 -04:00
idk
8170ddbce2 update index.html 2022-08-29 01:00:51 -04:00
idk
cd87569359 update EXAMPLE.html 2022-08-28 13:39:19 -04:00
idk
b0d86c9654 update DOCS.html 2022-08-28 13:39:16 -04:00
idk
d7f20533be update index.html 2022-08-28 13:39:08 -04:00
idk
3f39d265f7 update DESC.html 2022-08-28 13:39:03 -04:00
idk
962259e26c update index.html 2022-08-28 13:39:00 -04:00
idk
1ccf3ab24b Proxy convenience function 2022-08-26 00:03:17 -04:00
idk
7e722e4f1f update modules 2022-08-05 12:23:06 -04:00
idk
19f1acd68f update DOCS.html 2022-08-05 12:21:24 -04:00
idk
56d8c1b12c bump version 2022-08-05 12:21:10 -04:00
idk
ca28f25f6b Adds TLS support too. 2022-08-05 12:20:52 -04:00
idk
870d953e43 also add convenience functions for TLS 2022-08-04 21:37:51 -04:00
22 changed files with 1221 additions and 256 deletions

3
.gitignore vendored
View File

@@ -14,3 +14,6 @@
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/
data-dir* data-dir*
i2pkeys/
onionkeys/
tlskeys/

View File

@@ -7,6 +7,7 @@
<meta name="description" content="onramp.git" /> <meta name="description" content="onramp.git" />
<meta name="keywords" content="main" /> <meta name="keywords" content="main" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link rel="stylesheet" type="text/css" href="showhider.css" />
</head> </head>
<body> <body>
<div id="navbar"> <div id="navbar">
@@ -16,6 +17,11 @@
<div id="shownav"> <div id="shownav">
<div id="hidenav"> <div id="hidenav">
<ul> <ul>
<li>
<a href="..">
Up one level ^
</a>
</li>
<li> <li>
<a href="index.html"> <a href="index.html">
index index
@@ -45,11 +51,23 @@
</div> </div>
</div> </div>
<h1> <h1>
<a href="#onramp" rel="nofollow">
<span></span>
</a>
onramp onramp
</h1> </h1>
<p> <p>
An above-all easy to use library for setting up Tor and I2P services and clients. An above-all easy to use library for setting up Tor and I2P services and clients.
</p> </p>
<div id="sourcecode">
<ul>
<li>
<a href="https://github.com/eyedeekay/onramp.git">
Source Code: (https://github.com/eyedeekay/onramp.git)
</a>
</li>
</ul>
</div>
<div> <div>
<a href="#show"> <a href="#show">
Show license Show license

218
DOCS.html
View File

@@ -7,6 +7,7 @@
<meta name="description" content="onramp.git" /> <meta name="description" content="onramp.git" />
<meta name="keywords" content="main" /> <meta name="keywords" content="main" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link rel="stylesheet" type="text/css" href="showhider.css" />
</head> </head>
<body> <body>
<div id="navbar"> <div id="navbar">
@@ -16,6 +17,11 @@
<div id="shownav"> <div id="shownav">
<div id="hidenav"> <div id="hidenav">
<ul> <ul>
<li>
<a href="..">
Up one level ^
</a>
</li>
<li> <li>
<a href="index.html"> <a href="index.html">
index index
@@ -45,45 +51,65 @@
</div> </div>
</div> </div>
<h1> <h1>
<a href="#onramp-i2p-and-tor-library" rel="nofollow">
<span></span>
</a>
Onramp I2P and Tor Library Onramp I2P and Tor Library
</h1> </h1>
<p> <p>
<a href="http://pkg.go.dev/." rel="nofollow"> <a href="http://pkg.go.dev/." rel="nofollow">
<img src="https://img.shields.io/badge/pkg.go.dev-doc-blue" alt="GoDoc"/> <img src="https://img.shields.io/badge/pkg.go.dev-doc-blue" alt="GoDoc">
</a> </a>
<a href="https://goreportcard.com/report/." rel="nofollow"> <a href="https://goreportcard.com/report/." rel="nofollow">
<img src="https://goreportcard.com/badge/." alt="Go Report Card"/> <img src="https://goreportcard.com/badge/." alt="Go Report Card">
</a> </a>
</p> </p>
<h2> <h2>
<a href="#variables" rel="nofollow">
<span></span>
</a>
Variables Variables
</h2> </h2>
<p> <p>
I2P_KEYSTORE_PATH is the place where I2P Keys will be saved. I2P_KEYSTORE_PATH is the place where I2P Keys will be saved.
it defaults to the directory “i2pkeys” current working directory it defaults to the directory &#34;i2pkeys&#34; current working directory
reference it by calling I2PKeystorePath() to check for errors reference it by calling I2PKeystorePath() to check for errors
</p> </p>
<pre><code>var I2P_KEYSTORE_PATH = i2pdefault <div>
</code></pre> <pre>var I2P_KEYSTORE_PATH = i2pdefault
</pre>
</div>
<p> <p>
ONION_KEYSTORE_PATH is the place where Onion Keys will be saved. ONION_KEYSTORE_PATH is the place where Onion Keys will be saved.
it defaults to the directory onionkeys current working directory it defaults to the directory &#34;onionkeys&#34; current working directory
reference it by calling OnionKeystorePath() to check for errors reference it by calling OnionKeystorePath() to check for errors
</p> </p>
<pre><code>var ONION_KEYSTORE_PATH = tordefault <div>
</code></pre> <pre>var ONION_KEYSTORE_PATH = tordefault
<pre><code>var OPT_DEFAULTS = sam3.Options_Default </pre>
</code></pre> </div>
<div>
<pre>var OPT_DEFAULTS = sam3.Options_Default
</pre>
</div>
<p> <p>
SAM_ADDR is the default I2P SAM address. It can be overridden by the SAM_ADDR is the default I2P SAM address. It can be overridden by the
struct or by changing this variable. struct or by changing this variable.
</p> </p>
<pre><code>var SAM_ADDR = &#34;127.0.0.1:7656&#34; <div>
</code></pre> <pre>var SAM_ADDR = &#34;127.0.0.1:7656&#34;
</pre>
</div>
<h2> <h2>
<a href="#functions" rel="nofollow">
<span></span>
</a>
Functions Functions
</h2> </h2>
<h3> <h3>
<a href="#func-closeallgarlic" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L211" rel="nofollow"> <a href="/garlic.go#L211" rel="nofollow">
CloseAllGarlic CloseAllGarlic
@@ -99,6 +125,9 @@
affect objects instantiated by an app. affect objects instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-closeallonion" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L174" rel="nofollow"> <a href="/onion.go#L174" rel="nofollow">
CloseAllOnion CloseAllOnion
@@ -114,6 +143,9 @@
affect objects instantiated by an app. affect objects instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-closegarlic" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L220" rel="nofollow"> <a href="/garlic.go#L220" rel="nofollow">
CloseGarlic CloseGarlic
@@ -129,6 +161,9 @@
objects instantiated by an app. objects instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-closeonion" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L183" rel="nofollow"> <a href="/onion.go#L183" rel="nofollow">
CloseOnion CloseOnion
@@ -144,6 +179,23 @@
objects instantiated by an app. objects instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-createtlscertificate" rel="nofollow">
<span></span>
</a>
func
<a href="/tls.go#L20" rel="nofollow">
CreateTLSCertificate
</a>
</h3>
<p>
<code>
func CreateTLSCertificate(tlsHost string, tlsCert, tlsKey *string) error
</code>
</p>
<h3>
<a href="#func-deletegarlickeys" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L159" rel="nofollow"> <a href="/garlic.go#L159" rel="nofollow">
DeleteGarlicKeys DeleteGarlicKeys
@@ -161,6 +213,9 @@
address. address.
</p> </p>
<h3> <h3>
<a href="#func-deletei2pkeystore" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L60" rel="nofollow"> <a href="/common.go#L60" rel="nofollow">
DeleteI2PKeyStore DeleteI2PKeyStore
@@ -175,6 +230,9 @@
DeleteI2PKeyStore deletes the I2P Keystore. DeleteI2PKeyStore deletes the I2P Keystore.
</p> </p>
<h3> <h3>
<a href="#func-deleteonionkeys" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L216" rel="nofollow"> <a href="/onion.go#L216" rel="nofollow">
DeleteOnionKeys DeleteOnionKeys
@@ -190,6 +248,9 @@
keystore + tunName. keystore + tunName.
</p> </p>
<h3> <h3>
<a href="#func-deletetorkeystore" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L78" rel="nofollow"> <a href="/common.go#L78" rel="nofollow">
DeleteTorKeyStore DeleteTorKeyStore
@@ -204,6 +265,9 @@
DeleteTorKeyStore deletes the Onion Keystore. DeleteTorKeyStore deletes the Onion Keystore.
</p> </p>
<h3> <h3>
<a href="#func-dial" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L85" rel="nofollow"> <a href="/common.go#L85" rel="nofollow">
Dial Dial
@@ -220,6 +284,9 @@
if the address ends in anything else, it returns a Tor connection. if the address ends in anything else, it returns a Tor connection.
</p> </p>
<h3> <h3>
<a href="#func-dialgarlic" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L246" rel="nofollow"> <a href="/garlic.go#L246" rel="nofollow">
DialGarlic DialGarlic
@@ -231,11 +298,14 @@
</code> </code>
</p> </p>
<p> <p>
DialGarlic returns a net.Conn for a garlic structures keys DialGarlic returns a net.Conn for a garlic structure&#39;s keys
corresponding to a structure managed by the onramp library corresponding to a structure managed by the onramp library
and not instantiated by an app. and not instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-dialonion" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L205" rel="nofollow"> <a href="/onion.go#L205" rel="nofollow">
DialOnion DialOnion
@@ -247,11 +317,14 @@
</code> </code>
</p> </p>
<p> <p>
DialOnion returns a net.Conn for a onion structures keys DialOnion returns a net.Conn for a onion structure&#39;s keys
corresponding to a structure managed by the onramp library corresponding to a structure managed by the onramp library
and not instantiated by an app. and not instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-getjoinedwd" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L17" rel="nofollow"> <a href="/common.go#L17" rel="nofollow">
GetJoinedWD GetJoinedWD
@@ -266,6 +339,9 @@
GetJoinedWD returns the working directory joined with the given path. GetJoinedWD returns the working directory joined with the given path.
</p> </p>
<h3> <h3>
<a href="#func-i2pkeys" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L173" rel="nofollow"> <a href="/garlic.go#L173" rel="nofollow">
I2PKeys I2PKeys
@@ -281,6 +357,9 @@
tunnel name. If none exist, they are created and stored. tunnel name. If none exist, they are created and stored.
</p> </p>
<h3> <h3>
<a href="#func-i2pkeystorepath" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L49" rel="nofollow"> <a href="/common.go#L49" rel="nofollow">
I2PKeystorePath I2PKeystorePath
@@ -297,6 +376,9 @@
not exist, it creates it. not exist, it creates it.
</p> </p>
<h3> <h3>
<a href="#func-listen" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L101" rel="nofollow"> <a href="/common.go#L101" rel="nofollow">
Listen Listen
@@ -311,9 +393,12 @@
Listen returns a listener for the given network and address. Listen returns a listener for the given network and address.
if network is i2p or garlic, it returns an I2P listener. if network is i2p or garlic, it returns an I2P listener.
if network is tor or onion, it returns an Onion listener. if network is tor or onion, it returns an Onion listener.
if keys ends with “.i2p”, it returns an I2P listener. if keys ends with &#34;.i2p&#34;, it returns an I2P listener.
</p> </p>
<h3> <h3>
<a href="#func-listengarlic" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L234" rel="nofollow"> <a href="/garlic.go#L234" rel="nofollow">
ListenGarlic ListenGarlic
@@ -325,11 +410,14 @@
</code> </code>
</p> </p>
<p> <p>
ListenGarlic returns a net.Listener for a garlic structures keys ListenGarlic returns a net.Listener for a garlic structure&#39;s keys
corresponding to a structure managed by the onramp library corresponding to a structure managed by the onramp library
and not instantiated by an app. and not instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-listenonion" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L193" rel="nofollow"> <a href="/onion.go#L193" rel="nofollow">
ListenOnion ListenOnion
@@ -341,11 +429,42 @@
</code> </code>
</p> </p>
<p> <p>
ListenOnion returns a net.Listener for a onion structures keys ListenOnion returns a net.Listener for a onion structure&#39;s keys
corresponding to a structure managed by the onramp library corresponding to a structure managed by the onramp library
and not instantiated by an app. and not instantiated by an app.
</p> </p>
<h3> <h3>
<a href="#func-newtlscertificate" rel="nofollow">
<span></span>
</a>
func
<a href="/tls.go#L114" rel="nofollow">
NewTLSCertificate
</a>
</h3>
<p>
<code>
func NewTLSCertificate(host string, priv *ecdsa.PrivateKey) ([]byte, error)
</code>
</p>
<h3>
<a href="#func-newtlscertificatealtnames" rel="nofollow">
<span></span>
</a>
func
<a href="/tls.go#L118" rel="nofollow">
NewTLSCertificateAltNames
</a>
</h3>
<p>
<code>
func NewTLSCertificateAltNames(priv *ecdsa.PrivateKey, hosts ...string) ([]byte, error)
</code>
</p>
<h3>
<a href="#func-torkeys" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L135" rel="nofollow"> <a href="/onion.go#L135" rel="nofollow">
TorKeys TorKeys
@@ -362,6 +481,9 @@
returned. If it does not exist, it will be generated. returned. If it does not exist, it will be generated.
</p> </p>
<h3> <h3>
<a href="#func-torkeystorepath" rel="nofollow">
<span></span>
</a>
func func
<a href="/common.go#L67" rel="nofollow"> <a href="/common.go#L67" rel="nofollow">
TorKeystorePath TorKeystorePath
@@ -378,9 +500,15 @@
not exist, it creates it. not exist, it creates it.
</p> </p>
<h2> <h2>
<a href="#types" rel="nofollow">
<span></span>
</a>
Types Types
</h2> </h2>
<h3> <h3>
<a href="#type-garlic" rel="nofollow">
<span></span>
</a>
type type
<a href="/garlic.go#L19" rel="nofollow"> <a href="/garlic.go#L19" rel="nofollow">
Garlic Garlic
@@ -396,6 +524,9 @@
has a valid I2PKeys and StreamSession. has a valid I2PKeys and StreamSession.
</p> </p>
<h4> <h4>
<a href="#func-newgarlic" rel="nofollow">
<span></span>
</a>
func func
<a href="/garlic.go#L140" rel="nofollow"> <a href="/garlic.go#L140" rel="nofollow">
NewGarlic NewGarlic
@@ -411,6 +542,9 @@
I2P streaming. I2P streaming.
</p> </p>
<h4> <h4>
<a href="#func-garlic-close" rel="nofollow">
<span></span>
</a>
func (*Garlic) func (*Garlic)
<a href="/garlic.go#L111" rel="nofollow"> <a href="/garlic.go#L111" rel="nofollow">
Close Close
@@ -422,9 +556,12 @@
</code> </code>
</p> </p>
<p> <p>
Close closes the Garlic structures sessions and listeners. Close closes the Garlic structure&#39;s sessions and listeners.
</p> </p>
<h4> <h4>
<a href="#func-garlic-deletekeys" rel="nofollow">
<span></span>
</a>
func (*Garlic) func (*Garlic)
<a href="/garlic.go#L134" rel="nofollow"> <a href="/garlic.go#L134" rel="nofollow">
DeleteKeys DeleteKeys
@@ -436,6 +573,9 @@
</code> </code>
</p> </p>
<h4> <h4>
<a href="#func-garlic-dial" rel="nofollow">
<span></span>
</a>
func (*Garlic) func (*Garlic)
<a href="/garlic.go#L99" rel="nofollow"> <a href="/garlic.go#L99" rel="nofollow">
Dial Dial
@@ -447,9 +587,12 @@
</code> </code>
</p> </p>
<p> <p>
Dial returns a net.Conn for the Garlic structures I2P keys. Dial returns a net.Conn for the Garlic structure&#39;s I2P keys.
</p> </p>
<h4> <h4>
<a href="#func-garlic-keys" rel="nofollow">
<span></span>
</a>
func (*Garlic) func (*Garlic)
<a href="/garlic.go#L126" rel="nofollow"> <a href="/garlic.go#L126" rel="nofollow">
Keys Keys
@@ -465,6 +608,9 @@
exist, they are created and stored. exist, they are created and stored.
</p> </p>
<h4> <h4>
<a href="#func-garlic-listen" rel="nofollow">
<span></span>
</a>
func (*Garlic) func (*Garlic)
<a href="/garlic.go#L81" rel="nofollow"> <a href="/garlic.go#L81" rel="nofollow">
Listen Listen
@@ -476,9 +622,12 @@
</code> </code>
</p> </p>
<p> <p>
Listen returns a net.Listener for the Garlic structures I2P keys. Listen returns a net.Listener for the Garlic structure&#39;s I2P keys.
</p> </p>
<h3> <h3>
<a href="#type-onion" rel="nofollow">
<span></span>
</a>
type type
<a href="/onion.go#L24" rel="nofollow"> <a href="/onion.go#L24" rel="nofollow">
Onion Onion
@@ -495,6 +644,9 @@
keys. keys.
</p> </p>
<h4> <h4>
<a href="#func-newonion" rel="nofollow">
<span></span>
</a>
func func
<a href="/onion.go#L126" rel="nofollow"> <a href="/onion.go#L126" rel="nofollow">
NewOnion NewOnion
@@ -509,6 +661,9 @@
NewOnion returns a new Onion object. NewOnion returns a new Onion object.
</p> </p>
<h4> <h4>
<a href="#func-onion-close" rel="nofollow">
<span></span>
</a>
func (*Onion) func (*Onion)
<a href="/onion.go#L109" rel="nofollow"> <a href="/onion.go#L109" rel="nofollow">
Close Close
@@ -523,6 +678,9 @@
Close closes the Onion Service and all associated resources. Close closes the Onion Service and all associated resources.
</p> </p>
<h4> <h4>
<a href="#func-onion-deletekeys" rel="nofollow">
<span></span>
</a>
func (*Onion) func (*Onion)
<a href="/onion.go#L121" rel="nofollow"> <a href="/onion.go#L121" rel="nofollow">
DeleteKeys DeleteKeys
@@ -539,6 +697,9 @@
address. address.
</p> </p>
<h4> <h4>
<a href="#func-onion-dial" rel="nofollow">
<span></span>
</a>
func (*Onion) func (*Onion)
<a href="/onion.go#L104" rel="nofollow"> <a href="/onion.go#L104" rel="nofollow">
Dial Dial
@@ -553,6 +714,9 @@
Dial returns a net.Conn to the given onion address or clearnet address. Dial returns a net.Conn to the given onion address or clearnet address.
</p> </p>
<h4> <h4>
<a href="#func-onion-keys" rel="nofollow">
<span></span>
</a>
func (*Onion) func (*Onion)
<a href="/onion.go#L114" rel="nofollow"> <a href="/onion.go#L114" rel="nofollow">
Keys Keys
@@ -567,6 +731,9 @@
Keys returns the keys for the Onion Keys returns the keys for the Onion
</p> </p>
<h4> <h4>
<a href="#func-onion-listen" rel="nofollow">
<span></span>
</a>
func (*Onion) func (*Onion)
<a href="/onion.go#L99" rel="nofollow"> <a href="/onion.go#L99" rel="nofollow">
Listen Listen
@@ -581,13 +748,22 @@
ListenOnion returns a net.Listener which will listen on an onion ListenOnion returns a net.Listener which will listen on an onion
address, and will automatically generate a keypair and store it. address, and will automatically generate a keypair and store it.
</p> </p>
<hr/> <hr>
<p> <p>
Readme created from Go doc with Readme created from Go doc with
<a href="https://github.com/posener/goreadme" rel="nofollow"> <a href="https://github.com/posener/goreadme" rel="nofollow">
goreadme goreadme
</a> </a>
</p> </p>
<div id="sourcecode">
<ul>
<li>
<a href="https://github.com/eyedeekay/onramp.git">
Source Code: (https://github.com/eyedeekay/onramp.git)
</a>
</li>
</ul>
</div>
<div> <div>
<a href="#show"> <a href="#show">
Show license Show license

12
DOCS.md
View File

@@ -62,6 +62,10 @@ objects instantiated by an app.
CloseOnion closes the Onion at the given index. It does not affect Onion CloseOnion closes the Onion at the given index. It does not affect Onion
objects instantiated by an app. objects instantiated by an app.
### func [CreateTLSCertificate](/tls.go#L20)
`func CreateTLSCertificate(tlsHost string, tlsCert, tlsKey *string) error`
### func [DeleteGarlicKeys](/garlic.go#L159) ### func [DeleteGarlicKeys](/garlic.go#L159)
`func DeleteGarlicKeys(tunName string) error` `func DeleteGarlicKeys(tunName string) error`
@@ -160,6 +164,14 @@ ListenOnion returns a net.Listener for a onion structure's keys
corresponding to a structure managed by the onramp library corresponding to a structure managed by the onramp library
and not instantiated by an app. and not instantiated by an app.
### func [NewTLSCertificate](/tls.go#L114)
`func NewTLSCertificate(host string, priv *ecdsa.PrivateKey) ([]byte, error)`
### func [NewTLSCertificateAltNames](/tls.go#L118)
`func NewTLSCertificateAltNames(priv *ecdsa.PrivateKey, hosts ...string) ([]byte, error)`
### func [TorKeys](/onion.go#L135) ### func [TorKeys](/onion.go#L135)
`func TorKeys(keyName string) (ed25519.KeyPair, error)` `func TorKeys(keyName string) (ed25519.KeyPair, error)`

View File

@@ -7,6 +7,7 @@
<meta name="description" content="onramp.git" /> <meta name="description" content="onramp.git" />
<meta name="keywords" content="main" /> <meta name="keywords" content="main" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link rel="stylesheet" type="text/css" href="showhider.css" />
</head> </head>
<body> <body>
<div id="navbar"> <div id="navbar">
@@ -16,6 +17,11 @@
<div id="shownav"> <div id="shownav">
<div id="hidenav"> <div id="hidenav">
<ul> <ul>
<li>
<a href="..">
Up one level ^
</a>
</li>
<li> <li>
<a href="index.html"> <a href="index.html">
index index
@@ -45,195 +51,232 @@
</div> </div>
</div> </div>
<h1> <h1>
<a href="#example-usage" rel="nofollow">
<span></span>
</a>
Example Usage Example Usage
</h1> </h1>
<h3> <h3>
<a href="#usage-as-instance-of-a-struct-listener" rel="nofollow">
<span></span>
</a>
Usage as instance of a struct, Listener Usage as instance of a struct, Listener
</h3> </h3>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;fmt&#34; <span>&#34;fmt&#34;</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;net/http&#34; <span>&#34;net/http&#34;</span>
&#34;github.com/eyedeekay/onramp&#34; <span>&#34;github.com/eyedeekay/onramp&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
garlic := &amp;onramp.Garlic{} <span>garlic</span> <span>:=</span> <span>&amp;</span><span>onramp</span><span>.</span><span>Garlic</span><span>{</span><span>}</span>
defer garlic.Close() <span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
listener, err := garlic.Listen() <span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>garlic</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer listener.Close() <span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
http.HandleFunc(&#34;/&#34;, func(w http.ResponseWriter, r *http.Request) { <span>http</span><span>.</span><span>HandleFunc</span><span>(</span><span>&#34;/&#34;</span><span>,</span> <span>func</span><span>(</span><span>w</span> <span>http</span><span>.</span><span>ResponseWriter</span><span>,</span> <span>r</span> <span>*</span><span>http</span><span>.</span><span>Request</span><span>)</span> <span>{</span>
fmt.Fprintf(w, &#34;Hello, %q&#34;, r.URL.Path) <span>fmt</span><span>.</span><span>Fprintf</span><span>(</span><span>w</span><span>,</span> <span>&#34;Hello, %q&#34;</span><span>,</span> <span>r</span><span>.</span><span>URL</span><span>.</span><span>Path</span><span>)</span>
}) <span>}</span><span>)</span>
if err := http.Serve(listener, nil); err != nil { <span>if</span> <span>err</span> <span>:=</span> <span>http</span><span>.</span><span>Serve</span><span>(</span><span>listener</span><span>,</span> <span>nil</span><span>)</span><span>;</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
} <span>}</span>
</code></pre> </pre>
</div>
<h3> <h3>
<a href="#usage-as-instance-of-a-struct-dialer" rel="nofollow">
<span></span>
</a>
Usage as instance of a struct, Dialer Usage as instance of a struct, Dialer
</h3> </h3>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;fmt&#34; <span>&#34;fmt&#34;</span>
&#34;io/ioutil&#34; <span>&#34;io/ioutil&#34;</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;net/http&#34; <span>&#34;net/http&#34;</span>
&#34;github.com/eyedeekay/onramp&#34; <span>&#34;github.com/eyedeekay/onramp&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
garlic := &amp;onramp.Garlic{} <span>garlic</span> <span>:=</span> <span>&amp;</span><span>onramp</span><span>.</span><span>Garlic</span><span>{</span><span>}</span>
defer garlic.Close() <span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
transport := http.Transport{ <span>transport</span> <span>:=</span> <span>http</span><span>.</span><span>Transport</span><span>{</span>
Dial: garlic.Dial, <span>Dial</span><span>:</span> <span>garlic</span><span>.</span><span>Dial</span><span>,</span>
} <span>}</span>
client := &amp;http.Client{ <span>client</span> <span>:=</span> <span>&amp;</span><span>http</span><span>.</span><span>Client</span><span>{</span>
Transport: &amp;transport, <span>Transport</span><span>:</span> <span>&amp;</span><span>transport</span><span>,</span>
} <span>}</span>
resp, err := client.Get(&#34;http://&#34; + listener.Addr().String() + &#34;/&#34;) <span>resp</span><span>,</span> <span>err</span> <span>:=</span> <span>client</span><span>.</span><span>Get</span><span>(</span><span>&#34;http://&#34;</span> <span>+</span> <span>listener</span><span>.</span><span>Addr</span><span>(</span><span>)</span><span>.</span><span>String</span><span>(</span><span>)</span> <span>+</span> <span>&#34;/&#34;</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer resp.Body.Close() <span>defer</span> <span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>(</span><span>)</span>
fmt.Println(resp.Status) <span>fmt</span><span>.</span><span>Println</span><span>(</span><span>resp</span><span>.</span><span>Status</span><span>)</span>
body, err := ioutil.ReadAll(resp.Body) <span>body</span><span>,</span> <span>err</span> <span>:=</span> <span>ioutil</span><span>.</span><span>ReadAll</span><span>(</span><span>resp</span><span>.</span><span>Body</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
fmt.Println(string(body)) <span>fmt</span><span>.</span><span>Println</span><span>(</span><span>string</span><span>(</span><span>body</span><span>)</span><span>)</span>
} <span>}</span>
</code></pre> </pre>
</div>
<h3> <h3>
<a href="#usage-as-instance-of-a-struct-listener-and-dialer-on-same-address" rel="nofollow">
<span></span>
</a>
Usage as instance of a struct, Listener and Dialer on same address Usage as instance of a struct, Listener and Dialer on same address
</h3> </h3>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;fmt&#34; <span>&#34;fmt&#34;</span>
&#34;io/ioutil&#34; <span>&#34;io/ioutil&#34;</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;net&#34; <span>&#34;net&#34;</span>
&#34;net/http&#34; <span>&#34;net/http&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
garlic := &amp;Garlic{} <span>garlic</span> <span>:=</span> <span>&amp;</span><span>Garlic</span><span>{</span><span>}</span>
defer garlic.Close() <span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
listener, err := garlic.Listen() <span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>garlic</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
log.Println(&#34;listener:&#34;, listener.Addr().String()) <span>log</span><span>.</span><span>Println</span><span>(</span><span>&#34;listener:&#34;</span><span>,</span> <span>listener</span><span>.</span><span>Addr</span><span>(</span><span>)</span><span>.</span><span>String</span><span>(</span><span>)</span><span>)</span>
defer listener.Close() <span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
http.HandleFunc(&#34;/&#34;, func(w http.ResponseWriter, r *http.Request) { <span>http</span><span>.</span><span>HandleFunc</span><span>(</span><span>&#34;/&#34;</span><span>,</span> <span>func</span><span>(</span><span>w</span> <span>http</span><span>.</span><span>ResponseWriter</span><span>,</span> <span>r</span> <span>*</span><span>http</span><span>.</span><span>Request</span><span>)</span> <span>{</span>
fmt.Fprintf(w, &#34;Hello, %q&#34;, r.URL.Path) <span>fmt</span><span>.</span><span>Fprintf</span><span>(</span><span>w</span><span>,</span> <span>&#34;Hello, %q&#34;</span><span>,</span> <span>r</span><span>.</span><span>URL</span><span>.</span><span>Path</span><span>)</span>
}) <span>}</span><span>)</span>
go Serve(listener) <span>go</span> <span>Serve</span><span>(</span><span>listener</span><span>)</span>
transport := http.Transport{ <span>transport</span> <span>:=</span> <span>http</span><span>.</span><span>Transport</span><span>{</span>
Dial: garlic.Dial, <span>Dial</span><span>:</span> <span>garlic</span><span>.</span><span>Dial</span><span>,</span>
} <span>}</span>
client := &amp;http.Client{ <span>client</span> <span>:=</span> <span>&amp;</span><span>http</span><span>.</span><span>Client</span><span>{</span>
Transport: &amp;transport, <span>Transport</span><span>:</span> <span>&amp;</span><span>transport</span><span>,</span>
} <span>}</span>
resp, err := client.Get(&#34;http://&#34; + listener.Addr().String() + &#34;/&#34;) <span>resp</span><span>,</span> <span>err</span> <span>:=</span> <span>client</span><span>.</span><span>Get</span><span>(</span><span>&#34;http://&#34;</span> <span>+</span> <span>listener</span><span>.</span><span>Addr</span><span>(</span><span>)</span><span>.</span><span>String</span><span>(</span><span>)</span> <span>+</span> <span>&#34;/&#34;</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer resp.Body.Close() <span>defer</span> <span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>(</span><span>)</span>
fmt.Println(resp.Status) <span>fmt</span><span>.</span><span>Println</span><span>(</span><span>resp</span><span>.</span><span>Status</span><span>)</span>
body, err := ioutil.ReadAll(resp.Body) <span>body</span><span>,</span> <span>err</span> <span>:=</span> <span>ioutil</span><span>.</span><span>ReadAll</span><span>(</span><span>resp</span><span>.</span><span>Body</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
fmt.Println(string(body)) <span>fmt</span><span>.</span><span>Println</span><span>(</span><span>string</span><span>(</span><span>body</span><span>)</span><span>)</span>
} <span>}</span>
func Serve(listener net.Listener) { <span>func</span> <span>Serve</span><span>(</span><span>listener</span> <span>net</span><span>.</span><span>Listener</span><span>)</span> <span>{</span>
if err := http.Serve(listener, nil); err != nil { <span>if</span> <span>err</span> <span>:=</span> <span>http</span><span>.</span><span>Serve</span><span>(</span><span>listener</span><span>,</span> <span>nil</span><span>)</span><span>;</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
} <span>}</span>
</code></pre> </pre>
</div>
<h3> <h3>
<a href="#usage-as-automatically-managed-listeners" rel="nofollow">
<span></span>
</a>
Usage as automatically-managed Listeners Usage as automatically-managed Listeners
</h3> </h3>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;fmt&#34; <span>&#34;fmt&#34;</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;net/http&#34; <span>&#34;net/http&#34;</span>
&#34;github.com/eyedeekay/onramp&#34; <span>&#34;github.com/eyedeekay/onramp&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
defer onramp.CloseAll() <span>defer</span> <span>onramp</span><span>.</span><span>CloseAll</span><span>(</span><span>)</span>
listener, err := onramp.Listen(&#34;tcp&#34;, &#34;service.i2p&#34;) <span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>onramp</span><span>.</span><span>Listen</span><span>(</span><span>&#34;tcp&#34;</span><span>,</span> <span>&#34;service.i2p&#34;</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer listener.Close() <span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
http.HandleFunc(&#34;/&#34;, func(w http.ResponseWriter, r *http.Request) { <span>http</span><span>.</span><span>HandleFunc</span><span>(</span><span>&#34;/&#34;</span><span>,</span> <span>func</span><span>(</span><span>w</span> <span>http</span><span>.</span><span>ResponseWriter</span><span>,</span> <span>r</span> <span>*</span><span>http</span><span>.</span><span>Request</span><span>)</span> <span>{</span>
fmt.Fprintf(w, &#34;Hello, %q&#34;, r.URL.Path) <span>fmt</span><span>.</span><span>Fprintf</span><span>(</span><span>w</span><span>,</span> <span>&#34;Hello, %q&#34;</span><span>,</span> <span>r</span><span>.</span><span>URL</span><span>.</span><span>Path</span><span>)</span>
}) <span>}</span><span>)</span>
if err := http.Serve(listener, nil); err != nil { <span>if</span> <span>err</span> <span>:=</span> <span>http</span><span>.</span><span>Serve</span><span>(</span><span>listener</span><span>,</span> <span>nil</span><span>)</span><span>;</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
} <span>}</span>
</code></pre> </pre>
</div>
<h3> <h3>
<a href="#usage-as-automatically-managed-dialers" rel="nofollow">
<span></span>
</a>
Usage as automatically-managed Dialers Usage as automatically-managed Dialers
</h3> </h3>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;fmt&#34; <span>&#34;fmt&#34;</span>
&#34;io/ioutil&#34; <span>&#34;io/ioutil&#34;</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;net/http&#34; <span>&#34;net/http&#34;</span>
&#34;github.com/eyedeekay/onramp&#34; <span>&#34;github.com/eyedeekay/onramp&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
defer onramp.CloseAll() <span>defer</span> <span>onramp</span><span>.</span><span>CloseAll</span><span>(</span><span>)</span>
transport := http.Transport{ <span>transport</span> <span>:=</span> <span>http</span><span>.</span><span>Transport</span><span>{</span>
Dial: onramp.Dial, <span>Dial</span><span>:</span> <span>onramp</span><span>.</span><span>Dial</span><span>,</span>
} <span>}</span>
client := &amp;http.Client{ <span>client</span> <span>:=</span> <span>&amp;</span><span>http</span><span>.</span><span>Client</span><span>{</span>
Transport: &amp;transport, <span>Transport</span><span>:</span> <span>&amp;</span><span>transport</span><span>,</span>
} <span>}</span>
resp, err := client.Get(&#34;http://&#34; + listener.Addr().String() + &#34;/&#34;) <span>resp</span><span>,</span> <span>err</span> <span>:=</span> <span>client</span><span>.</span><span>Get</span><span>(</span><span>&#34;http://&#34;</span> <span>+</span> <span>listener</span><span>.</span><span>Addr</span><span>(</span><span>)</span><span>.</span><span>String</span><span>(</span><span>)</span> <span>+</span> <span>&#34;/&#34;</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer resp.Body.Close() <span>defer</span> <span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>(</span><span>)</span>
fmt.Println(resp.Status) <span>fmt</span><span>.</span><span>Println</span><span>(</span><span>resp</span><span>.</span><span>Status</span><span>)</span>
body, err := ioutil.ReadAll(resp.Body) <span>body</span><span>,</span> <span>err</span> <span>:=</span> <span>ioutil</span><span>.</span><span>ReadAll</span><span>(</span><span>resp</span><span>.</span><span>Body</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
fmt.Println(string(body)) <span>fmt</span><span>.</span><span>Println</span><span>(</span><span>string</span><span>(</span><span>body</span><span>)</span><span>)</span>
} <span>}</span>
</code></pre> </pre>
</div>
<div id="sourcecode">
<ul>
<li>
<a href="https://github.com/eyedeekay/onramp.git">
Source Code: (https://github.com/eyedeekay/onramp.git)
</a>
</li>
</ul>
</div>
<div> <div>
<a href="#show"> <a href="#show">
Show license Show license

27
Makefile Normal file
View File

@@ -0,0 +1,27 @@
USER_GH=eyedeekay
VERSION=0.33.1
packagename=onramp
echo: fmt
@echo "type make version to do release $(VERSION)"
version:
github-release release -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(packagename) -t v$(VERSION) -d "version $(VERSION)"
del:
github-release delete -s $(GITHUB_TOKEN) -u $(USER_GH) -r $(packagename) -t v$(VERSION)
tar:
tar --exclude .git \
--exclude .go \
--exclude bin \
--exclude examples \
-cJvf ../$(packagename)_$(VERSION).orig.tar.xz .
link:
rm -f ../goSam
ln -sf . ../goSam
fmt:
find . -name '*.go' -exec gofmt -w -s {} \;

View File

@@ -16,6 +16,8 @@ function. For more information, check out the [godoc](http://pkg.go.dev/github.c
- **[Source Code](https://github.com/eyedeekay/onramp)** - **[Source Code](https://github.com/eyedeekay/onramp)**
STATUS: This project is maintained. I will respond to issues, pull requests, and feature requests within a few days.
Usage Usage
----- -----

View File

@@ -32,17 +32,23 @@ func GetJoinedWD(dir string) (string, error) {
var i2pdefault, i2pkserr = GetJoinedWD("i2pkeys") var i2pdefault, i2pkserr = GetJoinedWD("i2pkeys")
var tordefault, torkserr = GetJoinedWD("onionkeys") var tordefault, torkserr = GetJoinedWD("onionkeys")
var tlsdefault, tlskserr = GetJoinedWD("tlskeys")
// I2P_KEYSTORE_PATH is the place where I2P Keys will be saved. // I2P_KEYSTORE_PATH is the place where I2P Keys will be saved.
// it defaults to the directory "i2pkeys" current working directory // it defaults to the directory "i2pkeys" current working directory.
// reference it by calling I2PKeystorePath() to check for errors // reference it by calling I2PKeystorePath() to check for errors
var I2P_KEYSTORE_PATH = i2pdefault var I2P_KEYSTORE_PATH = i2pdefault
// ONION_KEYSTORE_PATH is the place where Onion Keys will be saved. // ONION_KEYSTORE_PATH is the place where Onion Keys will be saved.
// it defaults to the directory "onionkeys" current working directory // it defaults to the directory "onionkeys" current working directory.
// reference it by calling OnionKeystorePath() to check for errors // reference it by calling OnionKeystorePath() to check for errors
var ONION_KEYSTORE_PATH = tordefault var ONION_KEYSTORE_PATH = tordefault
// TLS_KEYSTORE_PATH is the place where TLS Keys will be saved.
// it defaults to the directory "tlskeys" current working directory.
// reference it by calling TLSKeystorePath() to check for errors
var TLS_KEYSTORE_PATH = tlsdefault
// I2PKeystorePath returns the path to the I2P Keystore. If the // I2PKeystorePath returns the path to the I2P Keystore. If the
// path is not set, it returns the default path. If the path does // path is not set, it returns the default path. If the path does
// not exist, it creates it. // not exist, it creates it.
@@ -79,6 +85,24 @@ func DeleteTorKeyStore() error {
return os.RemoveAll(ONION_KEYSTORE_PATH) return os.RemoveAll(ONION_KEYSTORE_PATH)
} }
// TLSKeystorePath returns the path to the TLS Keystore. If the
// path is not set, it returns the default path. If the path does
// not exist, it creates it.
func TLSKeystorePath() (string, error) {
if _, err := os.Stat(TLS_KEYSTORE_PATH); err != nil {
err := os.MkdirAll(TLS_KEYSTORE_PATH, 0755)
if err != nil {
return "", err
}
}
return TLS_KEYSTORE_PATH, nil
}
// DeleteTLSKeyStore deletes the TLS Keystore.
func DeleteTLSKeyStore() error {
return os.RemoveAll(TLS_KEYSTORE_PATH)
}
// Dial returns a connection for the given network and address. // Dial returns a connection for the given network and address.
// network is ignored. If the address ends in i2p, it returns an I2P connection. // network is ignored. If the address ends in i2p, it returns an I2P connection.
// if the address ends in anything else, it returns a Tor connection. // if the address ends in anything else, it returns a Tor connection.

195
garlic.go
View File

@@ -4,11 +4,14 @@
package onramp package onramp
import ( import (
"context"
"crypto/tls"
"fmt" "fmt"
"log" "log"
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/eyedeekay/i2pkeys" "github.com/eyedeekay/i2pkeys"
"github.com/eyedeekay/sam3" "github.com/eyedeekay/sam3"
@@ -19,18 +22,65 @@ import (
type Garlic struct { type Garlic struct {
*sam3.StreamListener *sam3.StreamListener
*sam3.StreamSession *sam3.StreamSession
i2pkeys.I2PKeys *sam3.DatagramSession
ServiceKeys *i2pkeys.I2PKeys
*sam3.SAM *sam3.SAM
name string name string
addr string addr string
opts []string opts []string
AddrMode int
TorrentMode bool
} }
var OPT_DEFAULTS = sam3.Options_Default const (
DEST_BASE32 = 0
DEST_HASH = 1
DEST_HASH_BYTES = 2
DEST_BASE32_TRUNCATED = 3
DEST_BASE64 = 4
DEST_BASE64_BYTES = 5
)
func (g *Garlic) Network() string {
if g.StreamListener != nil {
return "tcp"
} else {
return "udp"
}
}
func (g *Garlic) addrString(addr string) string {
if g.TorrentMode {
return addr + ".i2p"
}
return addr
}
func (g *Garlic) String() string {
var r string
switch g.AddrMode {
case DEST_HASH:
r = g.ServiceKeys.Address.DestHash().Hash()
case DEST_HASH_BYTES:
hash := g.ServiceKeys.Address.DestHash()
r = string(hash[:])
case DEST_BASE32_TRUNCATED:
r = strings.TrimSuffix(g.ServiceKeys.Address.Base32(), ".b32.i2p")
case DEST_BASE32:
r = g.ServiceKeys.Address.Base32()
case DEST_BASE64:
r = g.ServiceKeys.Address.Base64()
case DEST_BASE64_BYTES:
r = string(g.ServiceKeys.Address.Bytes())
default:
r = g.ServiceKeys.Address.DestHash().Hash()
}
return g.addrString(r) //r //strings.TrimLeft(strings.TrimRight(r, "\n"), "\n") //strings.TrimSpace(r)
}
func (g *Garlic) getName() string { func (g *Garlic) getName() string {
if g.name == "" { if g.name == "" {
return "onramp" return "onramp-garlic"
} }
return g.name return g.name
} }
@@ -60,15 +110,15 @@ func (g *Garlic) samSession() (*sam3.SAM, error) {
return g.SAM, nil return g.SAM, nil
} }
func (g Garlic) setupStreamSession() (*sam3.StreamSession, error) { func (g *Garlic) setupStreamSession() (*sam3.StreamSession, error) {
if g.StreamSession == nil { if g.StreamSession == nil {
var err error var err error
g.I2PKeys, err = g.Keys() g.ServiceKeys, err = g.Keys()
if err != nil { if err != nil {
return nil, fmt.Errorf("onramp setupStreamSession: %v", err) return nil, fmt.Errorf("onramp setupStreamSession: %v", err)
} }
log.Println("Creating stream session with keys:", g.I2PKeys.Address.Base32()) log.Println("Creating stream session with keys:", g.ServiceKeys.Address.Base32())
g.StreamSession, err = g.SAM.NewStreamSession(g.getName(), g.I2PKeys, g.getOptions()) g.StreamSession, err = g.SAM.NewStreamSession(g.getName(), *g.ServiceKeys, g.getOptions())
if err != nil { if err != nil {
return nil, fmt.Errorf("onramp setupStreamSession: %v", err) return nil, fmt.Errorf("onramp setupStreamSession: %v", err)
} }
@@ -77,8 +127,55 @@ func (g Garlic) setupStreamSession() (*sam3.StreamSession, error) {
return g.StreamSession, nil return g.StreamSession, nil
} }
func (g *Garlic) setupDatagramSession() (*sam3.DatagramSession, error) {
if g.DatagramSession == nil {
var err error
g.ServiceKeys, err = g.Keys()
if err != nil {
return nil, fmt.Errorf("onramp setupDatagramSession: %v", err)
}
log.Println("Creating datagram session with keys:", g.ServiceKeys.Address.Base32())
g.DatagramSession, err = g.SAM.NewDatagramSession(g.getName(), *g.ServiceKeys, g.getOptions(), 0)
if err != nil {
return nil, fmt.Errorf("onramp setupDatagramSession: %v", err)
}
return g.DatagramSession, nil
}
return g.DatagramSession, nil
}
// NewListener returns a net.Listener for the Garlic structure's I2P keys.
// accepts a variable list of arguments, arguments after the first one are ignored.
func (g *Garlic) NewListener(n, addr string) (net.Listener, error) {
return g.Listen(n)
}
// Listen returns a net.Listener for the Garlic structure's I2P keys. // Listen returns a net.Listener for the Garlic structure's I2P keys.
func (g *Garlic) Listen() (net.Listener, error) { // accepts a variable list of arguments, arguments after the first one are ignored.
func (g *Garlic) Listen(args ...string) (net.Listener, error) {
return g.OldListen(args...)
}
// OldListen returns a net.Listener for the Garlic structure's I2P keys.
// accepts a variable list of arguments, arguments after the first one are ignored.
func (g *Garlic) OldListen(args ...string) (net.Listener, error) {
if len(args) > 0 {
if args[0] == "tcp" || args[0] == "tcp6" || args[0] == "st" || args[0] == "st6" {
return g.ListenStream()
} else if args[0] == "udp" || args[0] == "udp6" || args[0] == "dg" || args[0] == "dg6" {
pk, err := g.ListenPacket()
if err != nil {
return nil, err
}
return pk.(*sam3.DatagramSession), nil
}
}
return g.ListenStream()
}
// Listen returns a net.Listener for the Garlic structure's I2P keys.
func (g *Garlic) ListenStream() (net.Listener, error) {
var err error var err error
if g.SAM, err = g.samSession(); err != nil { if g.SAM, err = g.samSession(); err != nil {
return nil, fmt.Errorf("onramp NewGarlic: %v", err) return nil, fmt.Errorf("onramp NewGarlic: %v", err)
@@ -95,8 +192,63 @@ func (g *Garlic) Listen() (net.Listener, error) {
return g.StreamListener, nil return g.StreamListener, nil
} }
// ListenPacket returns a net.PacketConn for the Garlic structure's I2P keys.
func (g *Garlic) ListenPacket() (net.PacketConn, error) {
var err error
if g.SAM, err = g.samSession(); err != nil {
return nil, fmt.Errorf("onramp NewGarlic: %v", err)
}
if g.DatagramSession, err = g.setupDatagramSession(); err != nil {
return nil, fmt.Errorf("onramp Listen: %v", err)
}
return g.DatagramSession, nil
}
// ListenTLS returns a net.Listener for the Garlic structure's I2P keys,
// which also uses TLS either for additional encryption, authentication,
// or browser-compatibility.
func (g *Garlic) ListenTLS(args ...string) (net.Listener, error) {
listener, err := g.Listen(args...)
if err != nil {
return nil, err
}
cert, err := g.TLSKeys()
if err != nil {
return nil, fmt.Errorf("onramp ListenTLS: %v", err)
}
if len(args) > 0 {
if args[0] == "tcp" || args[0] == "tcp6" || args[0] == "st" || args[0] == "st6" {
return tls.NewListener(
g.StreamListener,
&tls.Config{
Certificates: []tls.Certificate{cert},
},
), nil
} else if args[0] == "udp" || args[0] == "udp6" || args[0] == "dg" || args[0] == "dg6" {
return tls.NewListener(
g.DatagramSession,
&tls.Config{
Certificates: []tls.Certificate{cert},
},
), nil
}
} else {
g.StreamListener = listener.(*sam3.StreamListener)
}
return tls.NewListener(
g.StreamListener,
&tls.Config{
Certificates: []tls.Certificate{cert},
},
), nil
}
// Dial returns a net.Conn for the Garlic structure's I2P keys. // Dial returns a net.Conn for the Garlic structure's I2P keys.
func (g *Garlic) Dial(net, addr string) (net.Conn, error) { func (g *Garlic) Dial(net, addr string) (net.Conn, error) {
if !strings.Contains(addr, ".i2p") {
return &NullConn{}, nil
}
var err error var err error
if g.SAM, err = g.samSession(); err != nil { if g.SAM, err = g.samSession(); err != nil {
return nil, fmt.Errorf("onramp NewGarlic: %v", err) return nil, fmt.Errorf("onramp NewGarlic: %v", err)
@@ -107,6 +259,21 @@ func (g *Garlic) Dial(net, addr string) (net.Conn, error) {
return g.StreamSession.Dial(net, addr) return g.StreamSession.Dial(net, addr)
} }
// DialContext returns a net.Conn for the Garlic structure's I2P keys.
func (g *Garlic) DialContext(ctx context.Context, net, addr string) (net.Conn, error) {
if !strings.Contains(addr, ".i2p") {
return &NullConn{}, nil
}
var err error
if g.SAM, err = g.samSession(); err != nil {
return nil, fmt.Errorf("onramp NewGarlic: %v", err)
}
if g.StreamSession, err = g.setupStreamSession(); err != nil {
return nil, fmt.Errorf("onramp Dial: %v", err)
}
return g.StreamSession.DialContext(ctx, net, addr)
}
// Close closes the Garlic structure's sessions and listeners. // Close closes the Garlic structure's sessions and listeners.
func (g *Garlic) Close() error { func (g *Garlic) Close() error {
e1 := g.StreamSession.Close() e1 := g.StreamSession.Close()
@@ -123,12 +290,12 @@ func (g *Garlic) Close() error {
// Keys returns the I2PKeys for the Garlic structure. If none // Keys returns the I2PKeys for the Garlic structure. If none
// exist, they are created and stored. // exist, they are created and stored.
func (g *Garlic) Keys() (i2pkeys.I2PKeys, error) { func (g *Garlic) Keys() (*i2pkeys.I2PKeys, error) {
keys, err := I2PKeys(g.getName(), g.getAddr()) keys, err := I2PKeys(g.getName(), g.getAddr())
if err != nil { if err != nil {
return i2pkeys.I2PKeys{}, fmt.Errorf("onramp Keys: %v", err) return &i2pkeys.I2PKeys{}, fmt.Errorf("onramp Keys: %v", err)
} }
return keys, nil return &keys, nil
} }
func (g *Garlic) DeleteKeys() error { func (g *Garlic) DeleteKeys() error {

11
garlic_config.go Normal file
View File

@@ -0,0 +1,11 @@
package onramp
import "github.com/eyedeekay/sam3"
var OPT_DEFAULTS = sam3.Options_Default
var OPT_WIDE = sam3.Options_Wide
var OPT_HUGE = sam3.Options_Humongous
var OPT_LARGE = sam3.Options_Large
var OPT_MEDIUM = sam3.Options_Medium
var OPT_SMALL = sam3.Options_Small

View File

@@ -4,6 +4,7 @@
package onramp package onramp
import ( import (
"crypto/tls"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@@ -18,7 +19,7 @@ func TestBareGarlic(t *testing.T) {
Sleep(5) Sleep(5)
garlic := &Garlic{} garlic := &Garlic{}
defer garlic.Close() defer garlic.Close()
listener, err := garlic.Listen() listener, err := garlic.ListenTLS()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -31,11 +32,14 @@ func TestBareGarlic(t *testing.T) {
Sleep(15) Sleep(15)
transport := http.Transport{ transport := http.Transport{
Dial: garlic.Dial, Dial: garlic.Dial,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
} }
client := &http.Client{ client := &http.Client{
Transport: &transport, Transport: &transport,
} }
resp, err := client.Get("http://" + listener.Addr().String() + "/") resp, err := client.Get("https://" + listener.Addr().String() + "/")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -46,6 +50,7 @@ func TestBareGarlic(t *testing.T) {
t.Error(err) t.Error(err)
} }
fmt.Println(string(body)) fmt.Println(string(body))
Sleep(5)
} }
func Serve(listener net.Listener) { func Serve(listener net.Listener) {

29
go.mod
View File

@@ -4,12 +4,31 @@ go 1.18
require ( require (
github.com/cretz/bine v0.2.0 github.com/cretz/bine v0.2.0
github.com/eyedeekay/i2pkeys v0.0.0-20220803204630-910de44ac829 github.com/eyedeekay/i2pkeys v0.33.0
github.com/eyedeekay/sam3 v0.33.2 github.com/eyedeekay/sam3 v0.33.5
github.com/libp2p/go-libp2p v0.28.1
github.com/libp2p/go-yamux/v4 v4.0.0
github.com/multiformats/go-multiaddr v0.9.0
) )
require ( require (
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect github.com/ipfs/go-cid v0.4.1 // indirect
golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.2 // indirect
github.com/multiformats/go-multistream v0.4.1 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
) )

68
go.sum
View File

@@ -1,15 +1,18 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/eyedeekay/goSam v0.32.31-0.20210122211817-f97683379f23/go.mod h1:UgJnih/LpotwKriwVPOEa6yPDM2NDdVrKfLtS5DOLPE= github.com/eyedeekay/goSam v0.32.31-0.20210122211817-f97683379f23/go.mod h1:UgJnih/LpotwKriwVPOEa6yPDM2NDdVrKfLtS5DOLPE=
github.com/eyedeekay/i2pkeys v0.0.0-20220310052025-204d4ae6dcae/go.mod h1:W9KCm9lqZ+Ozwl3dwcgnpPXAML97+I8Jiht7o5A8YBM= github.com/eyedeekay/i2pkeys v0.0.0-20220310052025-204d4ae6dcae/go.mod h1:W9KCm9lqZ+Ozwl3dwcgnpPXAML97+I8Jiht7o5A8YBM=
github.com/eyedeekay/i2pkeys v0.0.0-20220803204630-910de44ac829 h1:uXKTvYvSGuzAHzmT0YgPu3XZjZOlH1lLwrgWkymz934= github.com/eyedeekay/i2pkeys v0.33.0 h1:5SzUyWxNjV6AvYv/WaI8J4dSgAfv7/WEps6pDLe2YSs=
github.com/eyedeekay/i2pkeys v0.0.0-20220803204630-910de44ac829/go.mod h1:W9KCm9lqZ+Ozwl3dwcgnpPXAML97+I8Jiht7o5A8YBM= github.com/eyedeekay/i2pkeys v0.33.0/go.mod h1:W9KCm9lqZ+Ozwl3dwcgnpPXAML97+I8Jiht7o5A8YBM=
github.com/eyedeekay/sam3 v0.32.32/go.mod h1:qRA9KIIVxbrHlkj+ZB+OoxFGFgdKeGp1vSgPw26eOVU= github.com/eyedeekay/sam3 v0.32.32/go.mod h1:qRA9KIIVxbrHlkj+ZB+OoxFGFgdKeGp1vSgPw26eOVU=
github.com/eyedeekay/sam3 v0.33.2 h1:WP+fD4oPxiE0cA+gTKRNiZo3SrGI2+5FkzrnU/6Mmz4= github.com/eyedeekay/sam3 v0.33.5 h1:mY2MmEG4W35AOpG/G7DOdAhFZWRwFxlm+NmIoub1Xnw=
github.com/eyedeekay/sam3 v0.33.2/go.mod h1:sPtlI4cRm7wD0UywOzLPvvdY1G++vBSK3n+jiIGqWlU= github.com/eyedeekay/sam3 v0.33.5/go.mod h1:sPtlI4cRm7wD0UywOzLPvvdY1G++vBSK3n+jiIGqWlU=
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY= github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A= github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
github.com/getlantern/go-socks5 v0.0.0-20171114193258-79d4dd3e2db5/go.mod h1:kGHRXch95rnGLHjER/GhhFiHvfnqNz7KqWD9kGfATHY= github.com/getlantern/go-socks5 v0.0.0-20171114193258-79d4dd3e2db5/go.mod h1:kGHRXch95rnGLHjER/GhhFiHvfnqNz7KqWD9kGfATHY=
@@ -20,29 +23,65 @@ github.com/getlantern/netx v0.0.0-20190110220209-9912de6f94fd/go.mod h1:wKdY0ikO
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA= github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/getlantern/ops v0.0.0-20200403153110-8476b16edcd6/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA= github.com/getlantern/ops v0.0.0-20200403153110-8476b16edcd6/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio v1.0.0/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk= github.com/google/renameio v1.0.0/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-libp2p v0.28.1 h1:YurK+ZAI6cKfASLJBVFkpVBdl3wGhFi6fusOt725ii8=
github.com/libp2p/go-libp2p v0.28.1/go.mod h1:s3Xabc9LSwOcnv9UD4nORnXKTsWkPMkIMB/JIGXVnzk=
github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ=
github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ=
github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0=
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
github.com/multiformats/go-multihash v0.2.2 h1:Uu7LWs/PmWby1gkj1S1DXx3zyd3aVabA4FiMKn/2tAc=
github.com/multiformats/go-multihash v0.2.2/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/riobard/go-x25519 v0.0.0-20190716001027-10cc4d8d0b33/go.mod h1:BjmVxzAnkLeoEbqHEerI4eSw6ua+RaIB0S4jMV21RAs= github.com/riobard/go-x25519 v0.0.0-20190716001027-10cc4d8d0b33/go.mod h1:BjmVxzAnkLeoEbqHEerI4eSw6ua+RaIB0S4jMV21RAs=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -50,8 +89,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -59,8 +99,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -72,10 +114,16 @@ golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=

View File

@@ -7,6 +7,7 @@
<meta name="description" content="onramp.git" /> <meta name="description" content="onramp.git" />
<meta name="keywords" content="main" /> <meta name="keywords" content="main" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link rel="stylesheet" type="text/css" href="showhider.css" />
</head> </head>
<body> <body>
<div id="navbar"> <div id="navbar">
@@ -16,6 +17,11 @@
<div id="shownav"> <div id="shownav">
<div id="hidenav"> <div id="hidenav">
<ul> <ul>
<li>
<a href="..">
Up one level ^
</a>
</li>
<li> <li>
<a href="index.html"> <a href="index.html">
index index
@@ -45,22 +51,23 @@
</div> </div>
</div> </div>
<h1> <h1>
<a href="/"> <a href="#onramp" rel="nofollow">
onramp <span></span>
</a> </a>
onramp
</h1> </h1>
<p> <p>
High-level, easy-to-use listeners and clients for I2P and onion URLs from Go. High-level, easy-to-use listeners and clients for I2P and onion URL&#39;s from Go.
Provides only the most widely-used functions in a basic way. It expects nothing Provides only the most widely-used functions in a basic way. It expects nothing
from the users, an otherwise empty instance of the structs will listen and dial from the users, an otherwise empty instance of the structs will listen and dial
I2P Streaming and Tor TCP sessions successfully. I2P Streaming and Tor TCP sessions successfully.
</p> </p>
<p> <p>
In all cases, it assumes that keys are persistent in that they are managed In all cases, it assumes that keys are &#34;persistent&#34; in that they are managed
maintained between usages of the same application in the same configuration. maintained between usages of the same application in the same configuration.
This means that hidden services will maintain their identities, and that clients This means that hidden services will maintain their identities, and that clients
will always have the same return addresses. If you dont want this behavior, will always have the same return addresses. If you don&#39;t want this behavior,
make sure to delete the keystore when your app closes or when your application make sure to delete the &#34;keystore&#34; when your app closes or when your application
needs to cycle keys by calling the needs to cycle keys by calling the
<code> <code>
Garlic.DeleteKeys() Garlic.DeleteKeys()
@@ -84,12 +91,18 @@
</strong> </strong>
</li> </li>
</ul> </ul>
<p>
STATUS: This project is maintained. I will respond to issues, pull requests, and feature requests within a few days.
</p>
<h2> <h2>
<a href="#usage" rel="nofollow">
<span></span>
</a>
Usage Usage
</h2> </h2>
<p> <p>
Basic usage is designed to be very simple, import the package and instantiate Basic usage is designed to be very simple, import the package and instantiate
a struct and youre ready to go. a struct and you&#39;re ready to go.
</p> </p>
<p> <p>
For more extensive examples, see: For more extensive examples, see:
@@ -98,6 +111,9 @@
</a> </a>
</p> </p>
<h3> <h3>
<a href="#i2p-garlic-usage" rel="nofollow">
<span></span>
</a>
I2P(Garlic) Usage: I2P(Garlic) Usage:
</h3> </h3>
<p> <p>
@@ -107,26 +123,31 @@
</code> </code>
struct. struct.
</p> </p>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;github.com/eyedeekay/onramp&#34; <span>&#34;github.com/eyedeekay/onramp&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
garlic := &amp;onramp.Garlic{} <span>garlic</span> <span>:=</span> <span>&amp;</span><span>onramp</span><span>.</span><span>Garlic</span><span>{</span><span>}</span>
defer garlic.Close() <span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
listener, err := garlic.Listen() <span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>garlic</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer listener.Close() <span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
} <span>}</span>
</code></pre> </pre>
</div>
<h3> <h3>
<a href="#tor-onion-usage" rel="nofollow">
<span></span>
</a>
Tor(Onion) Usage: Tor(Onion) Usage:
</h3> </h3>
<p> <p>
@@ -136,25 +157,36 @@ func main() {
</code> </code>
struct. struct.
</p> </p>
<pre><code> <div>
package main <pre>
<span>package</span> <span>main</span>
import ( <span>import</span> <span>(</span>
&#34;log&#34; <span>&#34;log&#34;</span>
&#34;github.com/eyedeekay/onramp&#34; <span>&#34;github.com/eyedeekay/onramp&#34;</span>
) <span>)</span>
func main() { <span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
onion := &amp;onramp.Onion{} <span>onion</span> <span>:=</span> <span>&amp;</span><span>onramp</span><span>.</span><span>Onion</span><span>{</span><span>}</span>
defer garlic.Close() <span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
listener, err := onion.Listen() <span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>onion</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
if err != nil { <span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
log.Fatal(err) <span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
} <span>}</span>
defer listener.Close() <span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
} <span>}</span>
</code></pre> </pre>
</div>
<div id="sourcecode">
<ul>
<li>
<a href="https://github.com/eyedeekay/onramp.git">
Source Code: (https://github.com/eyedeekay/onramp.git)
</a>
</li>
</ul>
</div>
<div> <div>
<a href="#show"> <a href="#show">
Show license Show license

44
nullconn.go Normal file
View File

@@ -0,0 +1,44 @@
package onramp
import (
"net"
"time"
)
type NullConn struct {
net.Conn
}
func (nc *NullConn) Read(b []byte) (n int, err error) {
return 0, nil
}
func (nc *NullConn) Write(b []byte) (n int, err error) {
return 0, nil
}
func (nc *NullConn) Close() error { return nil }
func (nc *NullConn) LocalAddr() net.Addr {
if nc.Conn != nil {
return nc.Conn.LocalAddr()
}
return &net.IPAddr{
IP: net.ParseIP("127.0.0.1"),
}
}
func (nc *NullConn) RemoteAddr() net.Addr {
if nc.Conn != nil {
return nc.Conn.RemoteAddr()
}
return &net.IPAddr{
IP: net.ParseIP("127.0.0.1"),
}
}
func (nc *NullConn) SetDeadline(t time.Time) error { return nil }
func (nc *NullConn) SetReadDeadline(t time.Time) error { return nil }
func (nc *NullConn) SetWriteDeadline(t time.Time) error { return nil }

View File

@@ -5,6 +5,7 @@ package onramp
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@@ -89,17 +90,49 @@ func (o *Onion) getDialer() *tor.Dialer {
func (o *Onion) getName() string { func (o *Onion) getName() string {
if o.name == "" { if o.name == "" {
o.name = "onramp" o.name = "onramp-onion"
} }
return o.name return o.name
} }
// ListenOnion returns a net.Listener which will listen on an onion // NewListener returns a net.Listener which will listen on an onion
// address, and will automatically generate a keypair and store it. // address, and will automatically generate a keypair and store it.
func (o *Onion) Listen() (net.Listener, error) { // the args are always ignored
func (o *Onion) NewListener(n, addr string) (net.Listener, error) {
return o.Listen(n)
}
// Listen returns a net.Listener which will listen on an onion
// address, and will automatically generate a keypair and store it.
// the args are always ignored
func (o *Onion) Listen(args ...string) (net.Listener, error) {
return o.OldListen(args...)
}
// OldListen returns a net.Listener which will listen on an onion
// address, and will automatically generate a keypair and store it.
// the args are always ignored
func (o *Onion) OldListen(args ...string) (net.Listener, error) {
return o.getTor().Listen(o.getContext(), o.getListenConf()) return o.getTor().Listen(o.getContext(), o.getListenConf())
} }
// ListenTLS returns a net.Listener which will apply TLS encryption
// to the onion listener, which will not be decrypted until it reaches
// the browser
func (o *Onion) ListenTLS(args ...string) (net.Listener, error) {
cert, err := o.TLSKeys()
if err != nil {
return nil, fmt.Errorf("onramp ListenTLS: %v", err)
}
l, err := o.getTor().Listen(o.getContext(), o.getListenConf())
return tls.NewListener(
l,
&tls.Config{
Certificates: []tls.Certificate{cert},
},
), nil
}
// Dial returns a net.Conn to the given onion address or clearnet address. // Dial returns a net.Conn to the given onion address or clearnet address.
func (o *Onion) Dial(net, addr string) (net.Conn, error) { func (o *Onion) Dial(net, addr string) (net.Conn, error) {
return o.getDialer().DialContext(o.getContext(), net, addr) return o.getDialer().DialContext(o.getContext(), net, addr)

View File

@@ -4,6 +4,7 @@
package onramp package onramp
import ( import (
"crypto/tls"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@@ -16,7 +17,7 @@ func TestBareOnion(t *testing.T) {
Sleep(5) Sleep(5)
onion := &Onion{} onion := &Onion{}
defer onion.Close() defer onion.Close()
listener, err := onion.Listen() listener, err := onion.ListenTLS()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -29,11 +30,14 @@ func TestBareOnion(t *testing.T) {
Sleep(15) Sleep(15)
transport := http.Transport{ transport := http.Transport{
Dial: onion.Dial, Dial: onion.Dial,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
} }
client := &http.Client{ client := &http.Client{
Transport: &transport, Transport: &transport,
} }
resp, err := client.Get("http://" + listener.Addr().String() + "/") resp, err := client.Get("https://" + listener.Addr().String() + "/")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@@ -44,5 +48,5 @@ func TestBareOnion(t *testing.T) {
} }
fmt.Println("Body:", string(body)) fmt.Println("Body:", string(body))
resp.Body.Close() resp.Body.Close()
Sleep(5)
} }

56
proxy.go Normal file
View File

@@ -0,0 +1,56 @@
package onramp
import (
"io"
"log"
"net"
"strings"
)
type OnrampProxy struct {
Onion
Garlic
}
// Proxy passes requests from a net.Listener to a remote server
// without touching them in any way. It can be used as a shortcut,
// set up a Garlic or Onion Listener and pass it, along with the
// address of a locally running service and the hidden service
// listener will expose the local service.
// Pass it a regular net.Listener(or a TLS listener if you like),
// and an I2P or Onion address, and it will act as a tunnel to a
// listening hidden service somewhere.
func (p *OnrampProxy) Proxy(list net.Listener, raddr string) error {
for {
conn, err := list.Accept()
if err != nil {
return err
}
go p.proxy(conn, raddr)
}
}
func (p *OnrampProxy) proxy(conn net.Conn, raddr string) {
var remote net.Conn
var err error
checkaddr := strings.Split(raddr, ":")[0]
if strings.HasSuffix(checkaddr, ".i2p") {
remote, err = p.Garlic.Dial("tcp", raddr)
} else if strings.HasSuffix(checkaddr, ".onion") {
remote, err = p.Onion.Dial("tcp", raddr)
} else {
remote, err = net.Dial("tcp", raddr)
}
if err != nil {
log.Fatalf("cannot dial to remote: %v", err)
}
defer remote.Close()
go io.Copy(remote, conn)
io.Copy(conn, remote)
}
var proxy *OnrampProxy = &OnrampProxy{}
func Proxy(list net.Listener, raddr string) error {
return proxy.Proxy(list, raddr)
}

View File

@@ -2,10 +2,11 @@
GITHUB_USER=eyedeekay GITHUB_USER=eyedeekay
GITHUB_REPO=onramp GITHUB_REPO=onramp
GITHUB_NAME="Removes unnecessary dependency"
GITHUB_DESCRIPTION=$(cat DESC.md) GITHUB_DESCRIPTION=$(cat DESC.md)
GITHUB_TAG=0.0.1 GITHUB_TAG=0.0.5
github-release --user "${GITHUB_USER}" \ github-release release --user "${GITHUB_USER}" \
--repo "${GITHUB_REPO}" \ --repo "${GITHUB_REPO}" \
--name "${GITHUB_NAME}" \ --name "${GITHUB_NAME}" \
--description "${GITHUB_DESCRIPTION}" \ --description "${GITHUB_DESCRIPTION}" \

10
showhider.css Normal file
View File

@@ -0,0 +1,10 @@
/* edgar showhider CSS file */
#show {display:none; }
#hide {display:block; }
#show:target {display: block; }
#hide:target {display: none; }
#shownav {display:none; }
#hidenav {display:block; }
#shownav:target {display: block; }
#hidenav:target {display: none; }

View File

@@ -153,5 +153,5 @@ input {
#navbar { #navbar {
float: right; float: right;
width: 10%; width: 15%;
} }

230
tls.go Normal file
View File

@@ -0,0 +1,230 @@
package onramp
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"fmt"
"math/big"
"net"
"os"
"path/filepath"
"strings"
"time"
"github.com/cretz/bine/torutil"
)
// TLSKeys returns the TLS certificate and key for the given Garlic.
// if no TLS keys exist, they will be generated. They will be valid for
// the .b32.i2p domain.
func (g *Garlic) TLSKeys() (tls.Certificate, error) {
keys, err := g.Keys()
if err != nil {
return tls.Certificate{}, err
}
base32 := keys.Addr().Base32()
return TLSKeys(base32)
}
// TLSKeys returns the TLS certificate and key for the given Onion.
// if no TLS keys exist, they will be generated. They will be valid for
// the .onion domain.
func (o *Onion) TLSKeys() (tls.Certificate, error) {
keys, err := o.Keys()
if err != nil {
return tls.Certificate{}, err
}
onionService := torutil.OnionServiceIDFromPrivateKey(keys.PrivateKey)
return TLSKeys(onionService)
}
// TLSKeys returns the TLS certificate and key for the given hostname.
func TLSKeys(tlsHost string) (tls.Certificate, error) {
tlsCert := tlsHost + ".crt"
tlsKey := tlsHost + ".pem"
if err := CreateTLSCertificate(tlsHost); nil != err {
return tls.Certificate{}, err
}
tlsKeystorePath, err := TLSKeystorePath()
if err != nil {
return tls.Certificate{}, err
}
tlsCertPath := filepath.Join(tlsKeystorePath, tlsCert)
tlsKeyPath := filepath.Join(tlsKeystorePath, tlsKey)
cert, err := tls.LoadX509KeyPair(tlsCertPath, tlsKeyPath)
if err != nil {
return cert, err
}
return cert, nil
}
// CreateTLSCertificate generates a TLS certificate for the given hostname,
// and stores it in the TLS keystore for the application. If the keys already
// exist, generation is skipped.
func CreateTLSCertificate(tlsHost string) error {
tlsCertName := tlsHost + ".crt"
tlsKeyName := tlsHost + ".pem"
tlsKeystorePath, err := TLSKeystorePath()
if err != nil {
return err
}
tlsCert := filepath.Join(tlsKeystorePath, tlsCertName)
tlsKey := filepath.Join(tlsKeystorePath, tlsKeyName)
_, certErr := os.Stat(tlsCert)
_, keyErr := os.Stat(tlsKey)
if certErr != nil || keyErr != nil {
if certErr != nil {
fmt.Printf("Unable to read TLS certificate '%s'\n", tlsCert)
}
if keyErr != nil {
fmt.Printf("Unable to read TLS key '%s'\n", tlsKey)
}
if err := createTLSCertificate(tlsHost); nil != err {
return err
}
}
return nil
}
func createTLSCertificate(host string) error {
fmt.Println("Generating TLS keys. This may take a minute...")
priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil {
return err
}
tlsCert, err := NewTLSCertificate(host, priv)
if nil != err {
return err
}
privStore, err := TLSKeystorePath()
if nil != err {
return err
}
certFile := filepath.Join(privStore, host+".crt")
// save the TLS certificate
certOut, err := os.Create(certFile)
if err != nil {
return fmt.Errorf("failed to open %s for writing: %s", host+".crt", err)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: tlsCert})
certOut.Close()
fmt.Printf("\tTLS certificate saved to: %s\n", host+".crt")
// save the TLS private key
privFile := filepath.Join(privStore, host+".pem")
keyOut, err := os.OpenFile(privFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("failed to open %s for writing: %v", privFile, err)
}
secp384r1, err := asn1.Marshal(asn1.ObjectIdentifier{1, 3, 132, 0, 34}) // http://www.ietf.org/rfc/rfc5480.txt
pem.Encode(keyOut, &pem.Block{Type: "EC PARAMETERS", Bytes: secp384r1})
ecder, err := x509.MarshalECPrivateKey(priv)
pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: ecder})
pem.Encode(keyOut, &pem.Block{Type: "CERTIFICATE", Bytes: tlsCert})
keyOut.Close()
fmt.Printf("\tTLS private key saved to: %s\n", privFile)
// CRL
crlFile := filepath.Join(privStore, host+".crl")
crlOut, err := os.OpenFile(crlFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("failed to open %s for writing: %s", crlFile, err)
}
crlcert, err := x509.ParseCertificate(tlsCert)
if err != nil {
return fmt.Errorf("Certificate with unknown critical extension was not parsed: %s", err)
}
now := time.Now()
revokedCerts := []pkix.RevokedCertificate{
{
SerialNumber: crlcert.SerialNumber,
RevocationTime: now,
},
}
crlBytes, err := crlcert.CreateCRL(rand.Reader, priv, revokedCerts, now, now)
if err != nil {
return fmt.Errorf("error creating CRL: %s", err)
}
_, err = x509.ParseDERCRL(crlBytes)
if err != nil {
return fmt.Errorf("error reparsing CRL: %s", err)
}
pem.Encode(crlOut, &pem.Block{Type: "X509 CRL", Bytes: crlBytes})
crlOut.Close()
fmt.Printf("\tTLS CRL saved to: %s\n", crlFile)
return nil
}
// NewTLSCertificate generates a new TLS certificate for the given hostname,
// returning it as bytes.
func NewTLSCertificate(host string, priv *ecdsa.PrivateKey) ([]byte, error) {
return NewTLSCertificateAltNames(priv, host)
}
// NewTLSCertificateAltNames generates a new TLS certificate for the given hostname,
// and a list of alternate names, returning it as bytes.
func NewTLSCertificateAltNames(priv *ecdsa.PrivateKey, hosts ...string) ([]byte, error) {
notBefore := time.Now()
notAfter := notBefore.Add(5 * 365 * 24 * time.Hour)
host := ""
if len(hosts) > 0 {
host = hosts[0]
}
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, err
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"I2P Anonymous Network"},
OrganizationalUnit: []string{"I2P"},
Locality: []string{"XX"},
StreetAddress: []string{"XX"},
Country: []string{"XX"},
CommonName: host,
},
NotBefore: notBefore,
NotAfter: notAfter,
SignatureAlgorithm: x509.ECDSAWithSHA512,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IsCA: true,
DNSNames: hosts[1:],
}
hosts = append(hosts, strings.Split(host, ",")...)
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return nil, err
}
return derBytes, nil
}