mirror of
https://github.com/go-i2p/onramp.git
synced 2025-09-06 12:47:50 -04:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cdad2747a7 | ||
![]() |
394c9f9fb8 | ||
![]() |
f32a695cff | ||
![]() |
41dcb29429 | ||
![]() |
0e2d9a60a4 | ||
![]() |
f654f2635b | ||
![]() |
eb11a4ec64 | ||
![]() |
e2e443e158 | ||
![]() |
c93b68c0ab | ||
![]() |
af628a80ce | ||
![]() |
c6b30ad4cb | ||
![]() |
002fd2f79c | ||
![]() |
2f2d359ffb | ||
![]() |
59c4ed7e73 | ||
![]() |
dc495c94f6 | ||
![]() |
64cb1842d0 | ||
![]() |
55f43b8382 | ||
![]() |
1c866297b5 | ||
![]() |
8170ddbce2 | ||
![]() |
cd87569359 | ||
![]() |
b0d86c9654 | ||
![]() |
d7f20533be | ||
![]() |
3f39d265f7 | ||
![]() |
962259e26c | ||
![]() |
1ccf3ab24b | ||
![]() |
7e722e4f1f | ||
![]() |
19f1acd68f | ||
![]() |
56d8c1b12c | ||
![]() |
ca28f25f6b | ||
![]() |
870d953e43 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,3 +14,6 @@
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
data-dir*
|
||||
i2pkeys/
|
||||
onionkeys/
|
||||
tlskeys/
|
18
DESC.html
18
DESC.html
@@ -7,6 +7,7 @@
|
||||
<meta name="description" content="onramp.git" />
|
||||
<meta name="keywords" content="main" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="showhider.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
@@ -16,6 +17,11 @@
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="..">
|
||||
Up one level ^
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
@@ -45,11 +51,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<h1>
|
||||
<a href="#onramp" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
onramp
|
||||
</h1>
|
||||
<p>
|
||||
An above-all easy to use library for setting up Tor and I2P services and clients.
|
||||
</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>
|
||||
<a href="#show">
|
||||
Show license
|
||||
|
218
DOCS.html
218
DOCS.html
@@ -7,6 +7,7 @@
|
||||
<meta name="description" content="onramp.git" />
|
||||
<meta name="keywords" content="main" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="showhider.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
@@ -16,6 +17,11 @@
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="..">
|
||||
Up one level ^
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
@@ -45,45 +51,65 @@
|
||||
</div>
|
||||
</div>
|
||||
<h1>
|
||||
<a href="#onramp-i2p-and-tor-library" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Onramp I2P and Tor Library
|
||||
</h1>
|
||||
<p>
|
||||
<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 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>
|
||||
</p>
|
||||
<h2>
|
||||
<a href="#variables" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Variables
|
||||
</h2>
|
||||
<p>
|
||||
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
|
||||
</p>
|
||||
<pre><code>var I2P_KEYSTORE_PATH = i2pdefault
|
||||
</code></pre>
|
||||
<div>
|
||||
<pre>var I2P_KEYSTORE_PATH = i2pdefault
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
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
|
||||
</p>
|
||||
<pre><code>var ONION_KEYSTORE_PATH = tordefault
|
||||
</code></pre>
|
||||
<pre><code>var OPT_DEFAULTS = sam3.Options_Default
|
||||
</code></pre>
|
||||
<div>
|
||||
<pre>var ONION_KEYSTORE_PATH = tordefault
|
||||
</pre>
|
||||
</div>
|
||||
<div>
|
||||
<pre>var OPT_DEFAULTS = sam3.Options_Default
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
SAM_ADDR is the default I2P SAM address. It can be overridden by the
|
||||
struct or by changing this variable.
|
||||
</p>
|
||||
<pre><code>var SAM_ADDR = "127.0.0.1:7656"
|
||||
</code></pre>
|
||||
<div>
|
||||
<pre>var SAM_ADDR = "127.0.0.1:7656"
|
||||
</pre>
|
||||
</div>
|
||||
<h2>
|
||||
<a href="#functions" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Functions
|
||||
</h2>
|
||||
<h3>
|
||||
<a href="#func-closeallgarlic" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/garlic.go#L211" rel="nofollow">
|
||||
CloseAllGarlic
|
||||
@@ -99,6 +125,9 @@
|
||||
affect objects instantiated by an app.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-closeallonion" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/onion.go#L174" rel="nofollow">
|
||||
CloseAllOnion
|
||||
@@ -114,6 +143,9 @@
|
||||
affect objects instantiated by an app.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-closegarlic" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/garlic.go#L220" rel="nofollow">
|
||||
CloseGarlic
|
||||
@@ -129,6 +161,9 @@
|
||||
objects instantiated by an app.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-closeonion" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/onion.go#L183" rel="nofollow">
|
||||
CloseOnion
|
||||
@@ -144,6 +179,23 @@
|
||||
objects instantiated by an app.
|
||||
</p>
|
||||
<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
|
||||
<a href="/garlic.go#L159" rel="nofollow">
|
||||
DeleteGarlicKeys
|
||||
@@ -161,6 +213,9 @@
|
||||
address.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-deletei2pkeystore" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L60" rel="nofollow">
|
||||
DeleteI2PKeyStore
|
||||
@@ -175,6 +230,9 @@
|
||||
DeleteI2PKeyStore deletes the I2P Keystore.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-deleteonionkeys" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/onion.go#L216" rel="nofollow">
|
||||
DeleteOnionKeys
|
||||
@@ -190,6 +248,9 @@
|
||||
keystore + tunName.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-deletetorkeystore" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L78" rel="nofollow">
|
||||
DeleteTorKeyStore
|
||||
@@ -204,6 +265,9 @@
|
||||
DeleteTorKeyStore deletes the Onion Keystore.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-dial" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L85" rel="nofollow">
|
||||
Dial
|
||||
@@ -220,6 +284,9 @@
|
||||
if the address ends in anything else, it returns a Tor connection.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-dialgarlic" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/garlic.go#L246" rel="nofollow">
|
||||
DialGarlic
|
||||
@@ -231,11 +298,14 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
DialGarlic returns a net.Conn for a garlic structure’s keys
|
||||
DialGarlic returns a net.Conn for a garlic structure's keys
|
||||
corresponding to a structure managed by the onramp library
|
||||
and not instantiated by an app.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-dialonion" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/onion.go#L205" rel="nofollow">
|
||||
DialOnion
|
||||
@@ -247,11 +317,14 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
DialOnion returns a net.Conn for a onion structure’s keys
|
||||
DialOnion returns a net.Conn for a onion structure's keys
|
||||
corresponding to a structure managed by the onramp library
|
||||
and not instantiated by an app.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-getjoinedwd" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L17" rel="nofollow">
|
||||
GetJoinedWD
|
||||
@@ -266,6 +339,9 @@
|
||||
GetJoinedWD returns the working directory joined with the given path.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-i2pkeys" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/garlic.go#L173" rel="nofollow">
|
||||
I2PKeys
|
||||
@@ -281,6 +357,9 @@
|
||||
tunnel name. If none exist, they are created and stored.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-i2pkeystorepath" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L49" rel="nofollow">
|
||||
I2PKeystorePath
|
||||
@@ -297,6 +376,9 @@
|
||||
not exist, it creates it.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-listen" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L101" rel="nofollow">
|
||||
Listen
|
||||
@@ -311,9 +393,12 @@
|
||||
Listen returns a listener for the given network and address.
|
||||
if network is i2p or garlic, it returns an I2P 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 ".i2p", it returns an I2P listener.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-listengarlic" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/garlic.go#L234" rel="nofollow">
|
||||
ListenGarlic
|
||||
@@ -325,11 +410,14 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
ListenGarlic returns a net.Listener for a garlic structure’s keys
|
||||
ListenGarlic returns a net.Listener for a garlic structure's keys
|
||||
corresponding to a structure managed by the onramp library
|
||||
and not instantiated by an app.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-listenonion" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/onion.go#L193" rel="nofollow">
|
||||
ListenOnion
|
||||
@@ -341,11 +429,42 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
ListenOnion returns a net.Listener for a onion structure’s keys
|
||||
ListenOnion returns a net.Listener for a onion structure's keys
|
||||
corresponding to a structure managed by the onramp library
|
||||
and not instantiated by an app.
|
||||
</p>
|
||||
<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
|
||||
<a href="/onion.go#L135" rel="nofollow">
|
||||
TorKeys
|
||||
@@ -362,6 +481,9 @@
|
||||
returned. If it does not exist, it will be generated.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#func-torkeystorepath" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/common.go#L67" rel="nofollow">
|
||||
TorKeystorePath
|
||||
@@ -378,9 +500,15 @@
|
||||
not exist, it creates it.
|
||||
</p>
|
||||
<h2>
|
||||
<a href="#types" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Types
|
||||
</h2>
|
||||
<h3>
|
||||
<a href="#type-garlic" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
type
|
||||
<a href="/garlic.go#L19" rel="nofollow">
|
||||
Garlic
|
||||
@@ -396,6 +524,9 @@
|
||||
has a valid I2PKeys and StreamSession.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-newgarlic" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/garlic.go#L140" rel="nofollow">
|
||||
NewGarlic
|
||||
@@ -411,6 +542,9 @@
|
||||
I2P streaming.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-garlic-close" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Garlic)
|
||||
<a href="/garlic.go#L111" rel="nofollow">
|
||||
Close
|
||||
@@ -422,9 +556,12 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
Close closes the Garlic structure’s sessions and listeners.
|
||||
Close closes the Garlic structure's sessions and listeners.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-garlic-deletekeys" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Garlic)
|
||||
<a href="/garlic.go#L134" rel="nofollow">
|
||||
DeleteKeys
|
||||
@@ -436,6 +573,9 @@
|
||||
</code>
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-garlic-dial" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Garlic)
|
||||
<a href="/garlic.go#L99" rel="nofollow">
|
||||
Dial
|
||||
@@ -447,9 +587,12 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
Dial returns a net.Conn for the Garlic structure’s I2P keys.
|
||||
Dial returns a net.Conn for the Garlic structure's I2P keys.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-garlic-keys" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Garlic)
|
||||
<a href="/garlic.go#L126" rel="nofollow">
|
||||
Keys
|
||||
@@ -465,6 +608,9 @@
|
||||
exist, they are created and stored.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-garlic-listen" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Garlic)
|
||||
<a href="/garlic.go#L81" rel="nofollow">
|
||||
Listen
|
||||
@@ -476,9 +622,12 @@
|
||||
</code>
|
||||
</p>
|
||||
<p>
|
||||
Listen returns a net.Listener for the Garlic structure’s I2P keys.
|
||||
Listen returns a net.Listener for the Garlic structure's I2P keys.
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#type-onion" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
type
|
||||
<a href="/onion.go#L24" rel="nofollow">
|
||||
Onion
|
||||
@@ -495,6 +644,9 @@
|
||||
keys.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-newonion" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func
|
||||
<a href="/onion.go#L126" rel="nofollow">
|
||||
NewOnion
|
||||
@@ -509,6 +661,9 @@
|
||||
NewOnion returns a new Onion object.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-onion-close" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Onion)
|
||||
<a href="/onion.go#L109" rel="nofollow">
|
||||
Close
|
||||
@@ -523,6 +678,9 @@
|
||||
Close closes the Onion Service and all associated resources.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-onion-deletekeys" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Onion)
|
||||
<a href="/onion.go#L121" rel="nofollow">
|
||||
DeleteKeys
|
||||
@@ -539,6 +697,9 @@
|
||||
address.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-onion-dial" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Onion)
|
||||
<a href="/onion.go#L104" rel="nofollow">
|
||||
Dial
|
||||
@@ -553,6 +714,9 @@
|
||||
Dial returns a net.Conn to the given onion address or clearnet address.
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-onion-keys" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Onion)
|
||||
<a href="/onion.go#L114" rel="nofollow">
|
||||
Keys
|
||||
@@ -567,6 +731,9 @@
|
||||
Keys returns the keys for the Onion
|
||||
</p>
|
||||
<h4>
|
||||
<a href="#func-onion-listen" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
func (*Onion)
|
||||
<a href="/onion.go#L99" rel="nofollow">
|
||||
Listen
|
||||
@@ -581,13 +748,22 @@
|
||||
ListenOnion returns a net.Listener which will listen on an onion
|
||||
address, and will automatically generate a keypair and store it.
|
||||
</p>
|
||||
<hr/>
|
||||
<hr>
|
||||
<p>
|
||||
Readme created from Go doc with
|
||||
<a href="https://github.com/posener/goreadme" rel="nofollow">
|
||||
goreadme
|
||||
</a>
|
||||
</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>
|
||||
<a href="#show">
|
||||
Show license
|
||||
|
12
DOCS.md
12
DOCS.md
@@ -62,6 +62,10 @@ objects instantiated by an app.
|
||||
CloseOnion closes the Onion at the given index. It does not affect Onion
|
||||
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(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
|
||||
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(keyName string) (ed25519.KeyPair, error)`
|
||||
|
351
EXAMPLE.html
351
EXAMPLE.html
@@ -7,6 +7,7 @@
|
||||
<meta name="description" content="onramp.git" />
|
||||
<meta name="keywords" content="main" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="showhider.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
@@ -16,6 +17,11 @@
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="..">
|
||||
Up one level ^
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
@@ -45,195 +51,232 @@
|
||||
</div>
|
||||
</div>
|
||||
<h1>
|
||||
<a href="#example-usage" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Example Usage
|
||||
</h1>
|
||||
<h3>
|
||||
<a href="#usage-as-instance-of-a-struct-listener" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Usage as instance of a struct, Listener
|
||||
</h3>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"fmt"</span>
|
||||
<span>"log"</span>
|
||||
<span>"net/http"</span>
|
||||
|
||||
"github.com/eyedeekay/onramp"
|
||||
)
|
||||
<span>"github.com/eyedeekay/onramp"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
garlic := &onramp.Garlic{}
|
||||
defer garlic.Close()
|
||||
listener, err := garlic.Listen()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, %q", r.URL.Path)
|
||||
})
|
||||
if err := http.Serve(listener, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>garlic</span> <span>:=</span> <span>&</span><span>onramp</span><span>.</span><span>Garlic</span><span>{</span><span>}</span>
|
||||
<span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>garlic</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>http</span><span>.</span><span>HandleFunc</span><span>(</span><span>"/"</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>
|
||||
<span>fmt</span><span>.</span><span>Fprintf</span><span>(</span><span>w</span><span>,</span> <span>"Hello, %q"</span><span>,</span> <span>r</span><span>.</span><span>URL</span><span>.</span><span>Path</span><span>)</span>
|
||||
<span>}</span><span>)</span>
|
||||
<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>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>}</span>
|
||||
</pre>
|
||||
</div>
|
||||
<h3>
|
||||
<a href="#usage-as-instance-of-a-struct-dialer" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Usage as instance of a struct, Dialer
|
||||
</h3>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"fmt"</span>
|
||||
<span>"io/ioutil"</span>
|
||||
<span>"log"</span>
|
||||
<span>"net/http"</span>
|
||||
|
||||
"github.com/eyedeekay/onramp"
|
||||
)
|
||||
<span>"github.com/eyedeekay/onramp"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
garlic := &onramp.Garlic{}
|
||||
defer garlic.Close()
|
||||
transport := http.Transport{
|
||||
Dial: garlic.Dial,
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
resp, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
fmt.Println(resp.Status)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
}
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>garlic</span> <span>:=</span> <span>&</span><span>onramp</span><span>.</span><span>Garlic</span><span>{</span><span>}</span>
|
||||
<span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>transport</span> <span>:=</span> <span>http</span><span>.</span><span>Transport</span><span>{</span>
|
||||
<span>Dial</span><span>:</span> <span>garlic</span><span>.</span><span>Dial</span><span>,</span>
|
||||
<span>}</span>
|
||||
<span>client</span> <span>:=</span> <span>&</span><span>http</span><span>.</span><span>Client</span><span>{</span>
|
||||
<span>Transport</span><span>:</span> <span>&</span><span>transport</span><span>,</span>
|
||||
<span>}</span>
|
||||
<span>resp</span><span>,</span> <span>err</span> <span>:=</span> <span>client</span><span>.</span><span>Get</span><span>(</span><span>"http://"</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>"/"</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>fmt</span><span>.</span><span>Println</span><span>(</span><span>resp</span><span>.</span><span>Status</span><span>)</span>
|
||||
<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>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<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>
|
||||
<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
|
||||
</h3>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"fmt"</span>
|
||||
<span>"io/ioutil"</span>
|
||||
<span>"log"</span>
|
||||
<span>"net"</span>
|
||||
<span>"net/http"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
garlic := &Garlic{}
|
||||
defer garlic.Close()
|
||||
listener, err := garlic.Listen()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("listener:", listener.Addr().String())
|
||||
defer listener.Close()
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, %q", r.URL.Path)
|
||||
})
|
||||
go Serve(listener)
|
||||
transport := http.Transport{
|
||||
Dial: garlic.Dial,
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
resp, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
fmt.Println(resp.Status)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
}
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>garlic</span> <span>:=</span> <span>&</span><span>Garlic</span><span>{</span><span>}</span>
|
||||
<span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>garlic</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>log</span><span>.</span><span>Println</span><span>(</span><span>"listener:"</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>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>http</span><span>.</span><span>HandleFunc</span><span>(</span><span>"/"</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>
|
||||
<span>fmt</span><span>.</span><span>Fprintf</span><span>(</span><span>w</span><span>,</span> <span>"Hello, %q"</span><span>,</span> <span>r</span><span>.</span><span>URL</span><span>.</span><span>Path</span><span>)</span>
|
||||
<span>}</span><span>)</span>
|
||||
<span>go</span> <span>Serve</span><span>(</span><span>listener</span><span>)</span>
|
||||
<span>transport</span> <span>:=</span> <span>http</span><span>.</span><span>Transport</span><span>{</span>
|
||||
<span>Dial</span><span>:</span> <span>garlic</span><span>.</span><span>Dial</span><span>,</span>
|
||||
<span>}</span>
|
||||
<span>client</span> <span>:=</span> <span>&</span><span>http</span><span>.</span><span>Client</span><span>{</span>
|
||||
<span>Transport</span><span>:</span> <span>&</span><span>transport</span><span>,</span>
|
||||
<span>}</span>
|
||||
<span>resp</span><span>,</span> <span>err</span> <span>:=</span> <span>client</span><span>.</span><span>Get</span><span>(</span><span>"http://"</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>"/"</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>fmt</span><span>.</span><span>Println</span><span>(</span><span>resp</span><span>.</span><span>Status</span><span>)</span>
|
||||
<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>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<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) {
|
||||
if err := http.Serve(listener, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<span>func</span> <span>Serve</span><span>(</span><span>listener</span> <span>net</span><span>.</span><span>Listener</span><span>)</span> <span>{</span>
|
||||
<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>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>}</span>
|
||||
</pre>
|
||||
</div>
|
||||
<h3>
|
||||
<a href="#usage-as-automatically-managed-listeners" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Usage as automatically-managed Listeners
|
||||
</h3>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"fmt"</span>
|
||||
<span>"log"</span>
|
||||
<span>"net/http"</span>
|
||||
|
||||
"github.com/eyedeekay/onramp"
|
||||
)
|
||||
<span>"github.com/eyedeekay/onramp"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
defer onramp.CloseAll()
|
||||
listener, err := onramp.Listen("tcp", "service.i2p")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, %q", r.URL.Path)
|
||||
})
|
||||
if err := http.Serve(listener, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>defer</span> <span>onramp</span><span>.</span><span>CloseAll</span><span>(</span><span>)</span>
|
||||
<span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>onramp</span><span>.</span><span>Listen</span><span>(</span><span>"tcp"</span><span>,</span> <span>"service.i2p"</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>http</span><span>.</span><span>HandleFunc</span><span>(</span><span>"/"</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>
|
||||
<span>fmt</span><span>.</span><span>Fprintf</span><span>(</span><span>w</span><span>,</span> <span>"Hello, %q"</span><span>,</span> <span>r</span><span>.</span><span>URL</span><span>.</span><span>Path</span><span>)</span>
|
||||
<span>}</span><span>)</span>
|
||||
<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>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>}</span>
|
||||
|
||||
</code></pre>
|
||||
</pre>
|
||||
</div>
|
||||
<h3>
|
||||
<a href="#usage-as-automatically-managed-dialers" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Usage as automatically-managed Dialers
|
||||
</h3>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"fmt"</span>
|
||||
<span>"io/ioutil"</span>
|
||||
<span>"log"</span>
|
||||
<span>"net/http"</span>
|
||||
|
||||
"github.com/eyedeekay/onramp"
|
||||
)
|
||||
<span>"github.com/eyedeekay/onramp"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
defer onramp.CloseAll()
|
||||
transport := http.Transport{
|
||||
Dial: onramp.Dial,
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
resp, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
fmt.Println(resp.Status)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
}
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>defer</span> <span>onramp</span><span>.</span><span>CloseAll</span><span>(</span><span>)</span>
|
||||
<span>transport</span> <span>:=</span> <span>http</span><span>.</span><span>Transport</span><span>{</span>
|
||||
<span>Dial</span><span>:</span> <span>onramp</span><span>.</span><span>Dial</span><span>,</span>
|
||||
<span>}</span>
|
||||
<span>client</span> <span>:=</span> <span>&</span><span>http</span><span>.</span><span>Client</span><span>{</span>
|
||||
<span>Transport</span><span>:</span> <span>&</span><span>transport</span><span>,</span>
|
||||
<span>}</span>
|
||||
<span>resp</span><span>,</span> <span>err</span> <span>:=</span> <span>client</span><span>.</span><span>Get</span><span>(</span><span>"http://"</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>"/"</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>fmt</span><span>.</span><span>Println</span><span>(</span><span>resp</span><span>.</span><span>Status</span><span>)</span>
|
||||
<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>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<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>
|
||||
<a href="#show">
|
||||
Show license
|
||||
|
27
Makefile
Normal file
27
Makefile
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
USER_GH=eyedeekay
|
||||
VERSION=0.33.7
|
||||
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 {} \;
|
@@ -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)**
|
||||
|
||||
STATUS: This project is maintained. I will respond to issues, pull requests, and feature requests within a few days.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
28
common.go
28
common.go
@@ -32,17 +32,23 @@ func GetJoinedWD(dir string) (string, error) {
|
||||
|
||||
var i2pdefault, i2pkserr = GetJoinedWD("i2pkeys")
|
||||
var tordefault, torkserr = GetJoinedWD("onionkeys")
|
||||
var tlsdefault, tlskserr = GetJoinedWD("tlskeys")
|
||||
|
||||
// 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
|
||||
var I2P_KEYSTORE_PATH = i2pdefault
|
||||
|
||||
// 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
|
||||
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
|
||||
// path is not set, it returns the default path. If the path does
|
||||
// not exist, it creates it.
|
||||
@@ -79,6 +85,24 @@ func DeleteTorKeyStore() error {
|
||||
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.
|
||||
// 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.
|
||||
|
195
garlic.go
195
garlic.go
@@ -4,11 +4,14 @@
|
||||
package onramp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/eyedeekay/i2pkeys"
|
||||
"github.com/eyedeekay/sam3"
|
||||
@@ -19,18 +22,65 @@ import (
|
||||
type Garlic struct {
|
||||
*sam3.StreamListener
|
||||
*sam3.StreamSession
|
||||
i2pkeys.I2PKeys
|
||||
*sam3.DatagramSession
|
||||
ServiceKeys *i2pkeys.I2PKeys
|
||||
*sam3.SAM
|
||||
name string
|
||||
addr string
|
||||
opts []string
|
||||
name string
|
||||
addr 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 {
|
||||
if g.name == "" {
|
||||
return "onramp"
|
||||
return "onramp-garlic"
|
||||
}
|
||||
return g.name
|
||||
}
|
||||
@@ -60,15 +110,15 @@ func (g *Garlic) samSession() (*sam3.SAM, error) {
|
||||
return g.SAM, nil
|
||||
}
|
||||
|
||||
func (g Garlic) setupStreamSession() (*sam3.StreamSession, error) {
|
||||
func (g *Garlic) setupStreamSession() (*sam3.StreamSession, error) {
|
||||
if g.StreamSession == nil {
|
||||
var err error
|
||||
g.I2PKeys, err = g.Keys()
|
||||
g.ServiceKeys, err = g.Keys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("onramp setupStreamSession: %v", err)
|
||||
}
|
||||
log.Println("Creating stream session with keys:", g.I2PKeys.Address.Base32())
|
||||
g.StreamSession, err = g.SAM.NewStreamSession(g.getName(), g.I2PKeys, g.getOptions())
|
||||
log.Println("Creating stream session with keys:", g.ServiceKeys.Address.Base32())
|
||||
g.StreamSession, err = g.SAM.NewStreamSession(g.getName(), *g.ServiceKeys, g.getOptions())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("onramp setupStreamSession: %v", err)
|
||||
}
|
||||
@@ -77,8 +127,55 @@ func (g Garlic) setupStreamSession() (*sam3.StreamSession, error) {
|
||||
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.
|
||||
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
|
||||
if g.SAM, err = g.samSession(); err != nil {
|
||||
return nil, fmt.Errorf("onramp NewGarlic: %v", err)
|
||||
@@ -95,8 +192,63 @@ func (g *Garlic) Listen() (net.Listener, error) {
|
||||
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.
|
||||
func (g *Garlic) Dial(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)
|
||||
@@ -107,6 +259,21 @@ func (g *Garlic) Dial(net, addr string) (net.Conn, error) {
|
||||
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.
|
||||
func (g *Garlic) Close() error {
|
||||
e1 := g.StreamSession.Close()
|
||||
@@ -123,12 +290,12 @@ func (g *Garlic) Close() error {
|
||||
|
||||
// Keys returns the I2PKeys for the Garlic structure. If none
|
||||
// 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())
|
||||
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 {
|
||||
|
11
garlic_config.go
Normal file
11
garlic_config.go
Normal 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
|
@@ -4,6 +4,7 @@
|
||||
package onramp
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -18,7 +19,7 @@ func TestBareGarlic(t *testing.T) {
|
||||
Sleep(5)
|
||||
garlic := &Garlic{}
|
||||
defer garlic.Close()
|
||||
listener, err := garlic.Listen()
|
||||
listener, err := garlic.ListenTLS()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -31,11 +32,14 @@ func TestBareGarlic(t *testing.T) {
|
||||
Sleep(15)
|
||||
transport := http.Transport{
|
||||
Dial: garlic.Dial,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
resp, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
resp, err := client.Get("https://" + listener.Addr().String() + "/")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -46,6 +50,7 @@ func TestBareGarlic(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
Sleep(5)
|
||||
}
|
||||
|
||||
func Serve(listener net.Listener) {
|
||||
|
11
go.mod
11
go.mod
@@ -4,12 +4,13 @@ go 1.18
|
||||
|
||||
require (
|
||||
github.com/cretz/bine v0.2.0
|
||||
github.com/eyedeekay/i2pkeys v0.0.0-20220803204630-910de44ac829
|
||||
github.com/eyedeekay/sam3 v0.33.2
|
||||
github.com/eyedeekay/i2pkeys v0.33.7
|
||||
github.com/eyedeekay/sam3 v0.33.7
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect
|
||||
github.com/stretchr/testify v1.8.4 // indirect
|
||||
golang.org/x/crypto v0.11.0 // indirect
|
||||
golang.org/x/net v0.12.0 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
)
|
||||
|
77
go.sum
77
go.sum
@@ -1,81 +1,32 @@
|
||||
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/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/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-20220803204630-910de44ac829 h1:uXKTvYvSGuzAHzmT0YgPu3XZjZOlH1lLwrgWkymz934=
|
||||
github.com/eyedeekay/i2pkeys v0.0.0-20220803204630-910de44ac829/go.mod h1:W9KCm9lqZ+Ozwl3dwcgnpPXAML97+I8Jiht7o5A8YBM=
|
||||
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.2/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/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/golog v0.0.0-20201105130739-9586b8bde3a9/go.mod h1:ZyIjgH/1wTCl+B+7yH1DqrWp6MPJqESmwmEQ89ZfhvA=
|
||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
|
||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
|
||||
github.com/getlantern/netx v0.0.0-20190110220209-9912de6f94fd/go.mod h1:wKdY0ikOgzrWSeB9UyBVKPRhjXQ+vTb+BPeJuypUuNE=
|
||||
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/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/eyedeekay/i2pkeys v0.33.7 h1:cxqHSkl6b2lHyPJUtIQZBiipYf7NQVYqM1d3ub0MI4k=
|
||||
github.com/eyedeekay/i2pkeys v0.33.7/go.mod h1:W9KCm9lqZ+Ozwl3dwcgnpPXAML97+I8Jiht7o5A8YBM=
|
||||
github.com/eyedeekay/sam3 v0.33.7 h1:GPYHG4NHxvhqPbGNJ3wKvUQyZSTCmX17f5L5QvyefGs=
|
||||
github.com/eyedeekay/sam3 v0.33.7/go.mod h1:25cRGEFawSkbiPNSh7vTUIpRtEYLVLg/4J4He6LndAY=
|
||||
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/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.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.1.27/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-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-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
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/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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
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.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
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/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=
|
||||
honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
110
index.html
110
index.html
@@ -7,6 +7,7 @@
|
||||
<meta name="description" content="onramp.git" />
|
||||
<meta name="keywords" content="main" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="showhider.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
@@ -16,6 +17,11 @@
|
||||
<div id="shownav">
|
||||
<div id="hidenav">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="..">
|
||||
Up one level ^
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="index.html">
|
||||
index
|
||||
@@ -45,22 +51,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<h1>
|
||||
<a href="/">
|
||||
onramp
|
||||
<a href="#onramp" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
onramp
|
||||
</h1>
|
||||
<p>
|
||||
High-level, easy-to-use listeners and clients for I2P and onion URL’s from Go.
|
||||
High-level, easy-to-use listeners and clients for I2P and onion URL's from Go.
|
||||
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
|
||||
I2P Streaming and Tor TCP sessions successfully.
|
||||
</p>
|
||||
<p>
|
||||
In all cases, it assumes that keys are “persistent” in that they are managed
|
||||
In all cases, it assumes that keys are "persistent" in that they are managed
|
||||
maintained between usages of the same application in the same configuration.
|
||||
This means that hidden services will maintain their identities, and that clients
|
||||
will always have the same return addresses. If you don’t want this behavior,
|
||||
make sure to delete the “keystore” when your app closes or when your application
|
||||
will always have the same return addresses. If you don't want this behavior,
|
||||
make sure to delete the "keystore" when your app closes or when your application
|
||||
needs to cycle keys by calling the
|
||||
<code>
|
||||
Garlic.DeleteKeys()
|
||||
@@ -84,12 +91,18 @@
|
||||
</strong>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
STATUS: This project is maintained. I will respond to issues, pull requests, and feature requests within a few days.
|
||||
</p>
|
||||
<h2>
|
||||
<a href="#usage" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Usage
|
||||
</h2>
|
||||
<p>
|
||||
Basic usage is designed to be very simple, import the package and instantiate
|
||||
a struct and you’re ready to go.
|
||||
a struct and you're ready to go.
|
||||
</p>
|
||||
<p>
|
||||
For more extensive examples, see:
|
||||
@@ -98,6 +111,9 @@
|
||||
</a>
|
||||
</p>
|
||||
<h3>
|
||||
<a href="#i2p-garlic-usage" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
I2P(Garlic) Usage:
|
||||
</h3>
|
||||
<p>
|
||||
@@ -107,26 +123,31 @@
|
||||
</code>
|
||||
struct.
|
||||
</p>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"log"
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"log"</span>
|
||||
|
||||
"github.com/eyedeekay/onramp"
|
||||
)
|
||||
<span>"github.com/eyedeekay/onramp"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
garlic := &onramp.Garlic{}
|
||||
defer garlic.Close()
|
||||
listener, err := garlic.Listen()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
}
|
||||
</code></pre>
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>garlic</span> <span>:=</span> <span>&</span><span>onramp</span><span>.</span><span>Garlic</span><span>{</span><span>}</span>
|
||||
<span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>garlic</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>}</span>
|
||||
</pre>
|
||||
</div>
|
||||
<h3>
|
||||
<a href="#tor-onion-usage" rel="nofollow">
|
||||
<span></span>
|
||||
</a>
|
||||
Tor(Onion) Usage:
|
||||
</h3>
|
||||
<p>
|
||||
@@ -136,25 +157,36 @@ func main() {
|
||||
</code>
|
||||
struct.
|
||||
</p>
|
||||
<pre><code>
|
||||
package main
|
||||
<div>
|
||||
<pre>
|
||||
<span>package</span> <span>main</span>
|
||||
|
||||
import (
|
||||
"log"
|
||||
<span>import</span> <span>(</span>
|
||||
<span>"log"</span>
|
||||
|
||||
"github.com/eyedeekay/onramp"
|
||||
)
|
||||
<span>"github.com/eyedeekay/onramp"</span>
|
||||
<span>)</span>
|
||||
|
||||
func main() {
|
||||
onion := &onramp.Onion{}
|
||||
defer garlic.Close()
|
||||
listener, err := onion.Listen()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
}
|
||||
</code></pre>
|
||||
<span>func</span> <span>main</span><span>(</span><span>)</span> <span>{</span>
|
||||
<span>onion</span> <span>:=</span> <span>&</span><span>onramp</span><span>.</span><span>Onion</span><span>{</span><span>}</span>
|
||||
<span>defer</span> <span>garlic</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>listener</span><span>,</span> <span>err</span> <span>:=</span> <span>onion</span><span>.</span><span>Listen</span><span>(</span><span>)</span>
|
||||
<span>if</span> <span>err</span> <span>!=</span> <span>nil</span> <span>{</span>
|
||||
<span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span>
|
||||
<span>}</span>
|
||||
<span>defer</span> <span>listener</span><span>.</span><span>Close</span><span>(</span><span>)</span>
|
||||
<span>}</span>
|
||||
</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>
|
||||
<a href="#show">
|
||||
Show license
|
||||
|
44
nullconn.go
Normal file
44
nullconn.go
Normal 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 }
|
39
onion.go
39
onion.go
@@ -5,6 +5,7 @@ package onramp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -89,17 +90,49 @@ func (o *Onion) getDialer() *tor.Dialer {
|
||||
|
||||
func (o *Onion) getName() string {
|
||||
if o.name == "" {
|
||||
o.name = "onramp"
|
||||
o.name = "onramp-onion"
|
||||
}
|
||||
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.
|
||||
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())
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (o *Onion) Dial(net, addr string) (net.Conn, error) {
|
||||
return o.getDialer().DialContext(o.getContext(), net, addr)
|
||||
|
@@ -4,6 +4,7 @@
|
||||
package onramp
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -16,7 +17,7 @@ func TestBareOnion(t *testing.T) {
|
||||
Sleep(5)
|
||||
onion := &Onion{}
|
||||
defer onion.Close()
|
||||
listener, err := onion.Listen()
|
||||
listener, err := onion.ListenTLS()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -29,11 +30,14 @@ func TestBareOnion(t *testing.T) {
|
||||
Sleep(15)
|
||||
transport := http.Transport{
|
||||
Dial: onion.Dial,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
resp, err := client.Get("http://" + listener.Addr().String() + "/")
|
||||
resp, err := client.Get("https://" + listener.Addr().String() + "/")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -44,5 +48,5 @@ func TestBareOnion(t *testing.T) {
|
||||
}
|
||||
fmt.Println("Body:", string(body))
|
||||
resp.Body.Close()
|
||||
|
||||
Sleep(5)
|
||||
}
|
||||
|
56
proxy.go
Normal file
56
proxy.go
Normal 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)
|
||||
}
|
@@ -2,10 +2,11 @@
|
||||
|
||||
GITHUB_USER=eyedeekay
|
||||
GITHUB_REPO=onramp
|
||||
GITHUB_NAME="Removes unnecessary dependency"
|
||||
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}" \
|
||||
--name "${GITHUB_NAME}" \
|
||||
--description "${GITHUB_DESCRIPTION}" \
|
||||
|
10
showhider.css
Normal file
10
showhider.css
Normal 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; }
|
230
tls.go
Normal file
230
tls.go
Normal 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
|
||||
}
|
Reference in New Issue
Block a user