cretz / bine Goto Github PK
View Code? Open in Web Editor NEWGo library for accessing and embedding Tor clients and servers
License: MIT License
Go library for accessing and embedding Tor clients and servers
License: MIT License
Hey, I was trying to make executable on windows with statically linked libs.
I did Link says and build and put the directory I can build for Linux but I couldn't manage to build for windows what I'm doing wrong any idea?
My Operating system: Ubuntu / Amd64
I got this error when I try to build for windows amd64
cannot load github.com/cretz/bine/process/embedded/tor-0.3.5: no Go source files
Tree.
.
├── go.mod
├── go.sum
└── main.go
Main.go
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
"github.com/cretz/bine/process/embedded"
"github.com/cretz/bine/tor"
)
func main() {
// Start tor with default config (can set start conf's DebugWriter to os.Stdout for debug logs)
fmt.Println("Starting and registering onion service, please wait a couple of minutes...")
t, err := tor.Start(nil, &tor.StartConf{ProcessCreator: embedded.NewCreator()})
if err != nil {
log.Panicf("Unable to start Tor: %v", err)
}
defer t.Close()
// Wait at most a few minutes to publish the service
listenCtx, listenCancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer listenCancel()
// Create a v3 onion service to listen on any port but show as 80
onion, err := t.Listen(listenCtx, &tor.ListenConf{Version3: true, RemotePorts: []int{80}})
if err != nil {
log.Panicf("Unable to create onion service: %v", err)
}
defer onion.Close()
fmt.Printf("Open Tor browser and navigate to http://%v.onion\n", onion.ID)
fmt.Println("Press enter to exit")
// Serve the current folder from HTTP
errCh := make(chan error, 1)
go func() { errCh <- http.Serve(onion, http.FileServer(http.Dir("."))) }()
// End when enter is pressed
go func() {
fmt.Scanln()
errCh <- nil
}()
if err = <-errCh; err != nil {
log.Panicf("Failed serving: %v", err)
}
}
Sincerely, Electwix
I tried to build with this command
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CXX=x86_64-w64-mingw32-g++ CC=x86_64-w64-mingw32-gcc go build -x
but get this error
# github.com/cretz/bine/process/embedded/tor-0.3.5
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_api_get_provider_version':
/tmp/go-build/cgo-gcc-prolog:99: undefined reference to `tor_api_get_provider_version'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_new':
/tmp/go-build/cgo-gcc-prolog:128: undefined reference to `tor_main_configuration_new'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_set_command_line':
/tmp/go-build/cgo-gcc-prolog:150: undefined reference to `tor_main_configuration_set_command_line'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_setup_control_socket':
/tmp/go-build/cgo-gcc-prolog:168: undefined reference to `tor_main_configuration_setup_control_socket'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_run_main':
/tmp/go-build/cgo-gcc-prolog:187: undefined reference to `tor_run_main'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_free':
/tmp/go-build/cgo-gcc-prolog:114: undefined reference to `tor_main_configuration_free'
collect2: error: ld returned 1 exit status
Full-log
WORK=/tmp/go-build114901294
mkdir -p $WORK/b082/
cd /home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5
CGO_LDFLAGS='"-g" "-O2" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/core" "-ltor-app" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/lib" "-ltor-compress" "-ltor-evloop" "-ltor-tls" "-ltor-crypt-ops" "-lcurve25519_donna" "-ltor-geoip" "-ltor-process" "-ltor-time" "-ltor-fs" "-ltor-encoding" "-ltor-sandbox" "-ltor-container" "-ltor-net" "-ltor-thread" "-ltor-memarea" "-ltor-math" "-ltor-meminfo" "-ltor-osinfo" "-ltor-log" "-ltor-lock" "-ltor-fdio" "-ltor-string" "-ltor-term" "-ltor-smartlist-core" "-ltor-malloc" "-ltor-wallclock" "-ltor-err" "-ltor-intmath" "-ltor-ctime" "-ltor-trace" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/ext/keccak-tiny" "-lkeccak-tiny" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/ext/ed25519/ref10" "-led25519_ref10" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/ext/ed25519/donna" "-led25519_donna" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/trunnel" "-lor-trunnel" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/libevent/dist/lib" "-levent" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/xz/dist/lib" "-llzma" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/zlib/dist/lib" "-lz" "-L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/openssl/dist/lib" "-lssl" "-lcrypto" "-lws2_32" "-lcrypt32" "-lgdi32" "-liphlpapi" "-Wl,-Bstatic" "-lpthread"' /usr/lib/go-1.13/pkg/tool/linux_amd64/cgo -objdir $WORK/b082/ -importpath github.com/cretz/bine/process/embedded/tor-0.3.5 -- -I $WORK/b082/ -g -O2 -I/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/feature/api ./process.go
cd $WORK
x86_64-w64-mingw32-gcc -fno-caret-diagnostics -c -x c - -o /dev/null || true
x86_64-w64-mingw32-gcc -Qunused-arguments -c -x c - -o /dev/null || true
x86_64-w64-mingw32-gcc -fdebug-prefix-map=a=b -c -x c - -o /dev/null || true
x86_64-w64-mingw32-gcc -gno-record-gcc-switches -c -x c - -o /dev/null || true
cd $WORK/b082
TERM='dumb' x86_64-w64-mingw32-gcc -I /home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5 -m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=$WORK/b082=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -I/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/feature/api -o ./_x001.o -c _cgo_export.c
TERM='dumb' x86_64-w64-mingw32-gcc -I /home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5 -m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=$WORK/b082=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -I/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/feature/api -o ./_x002.o -c process.cgo2.c
TERM='dumb' x86_64-w64-mingw32-gcc -I /home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5 -m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=$WORK/b082=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -I/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/feature/api -o ./_cgo_main.o -c _cgo_main.c
cd /home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5
TERM='dumb' x86_64-w64-mingw32-gcc -I . -m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=$WORK/b082=/tmp/go-build -gno-record-gcc-switches -o $WORK/b082/_cgo_.o $WORK/b082/_cgo_main.o $WORK/b082/_x001.o $WORK/b082/_x002.o -g -O2 -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/core -ltor-app -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/lib -ltor-compress -ltor-evloop -ltor-tls -ltor-crypt-ops -lcurve25519_donna -ltor-geoip -ltor-process -ltor-time -ltor-fs -ltor-encoding -ltor-sandbox -ltor-container -ltor-net -ltor-thread -ltor-memarea -ltor-math -ltor-meminfo -ltor-osinfo -ltor-log -ltor-lock -ltor-fdio -ltor-string -ltor-term -ltor-smartlist-core -ltor-malloc -ltor-wallclock -ltor-err -ltor-intmath -ltor-ctime -ltor-trace -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/ext/keccak-tiny -lkeccak-tiny -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/ext/ed25519/ref10 -led25519_ref10 -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/ext/ed25519/donna -led25519_donna -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/tor/src/trunnel -lor-trunnel -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/libevent/dist/lib -levent -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/xz/dist/lib -llzma -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/zlib/dist/lib -lz -L/home/electwix/go/pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/../../../../tor-static/openssl/dist/lib -lssl -lcrypto -lws2_32 -lcrypt32 -lgdi32 -liphlpapi -Wl,-Bstatic -lpthread
# github.com/cretz/bine/process/embedded/tor-0.3.5
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_api_get_provider_version':
/tmp/go-build/cgo-gcc-prolog:99: undefined reference to `tor_api_get_provider_version'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_new':
/tmp/go-build/cgo-gcc-prolog:128: undefined reference to `tor_main_configuration_new'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_set_command_line':
/tmp/go-build/cgo-gcc-prolog:150: undefined reference to `tor_main_configuration_set_command_line'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_setup_control_socket':
/tmp/go-build/cgo-gcc-prolog:168: undefined reference to `tor_main_configuration_setup_control_socket'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_run_main':
/tmp/go-build/cgo-gcc-prolog:187: undefined reference to `tor_run_main'
/usr/bin/x86_64-w64-mingw32-ld: $WORK/b082/_x002.o: in function `_cgo_0b2b2d15ff5e_Cfunc_tor_main_configuration_free':
/tmp/go-build/cgo-gcc-prolog:114: undefined reference to `tor_main_configuration_free'
collect2: error: ld returned 1 exit status
I saw a golang based implementation by the Tor team for webrtc.
Do you think it's on your roadmap ?
I saw that it was a big effort by them..
Maybe it will make this project really perfect :)
How would that work? I tried just copying the private key named hs_ed25519_secret_key
from my site stored in /var/lib/tor
but I keep getting the wrong onion address when I try to load it. I also tried removing the line == ed25519v1-secret: type0 ==\0\0\0
to make the key 64 bytes but no luck. Can you write a Go module to do this?
Looking at the simple client:
https://github.com/cretz/bine/blob/master/examples/simpleclient/main.go
dialer, err := t.Dialer(dialCtx, nil)
If we want to have a new dialer, is it safe to just overwrite the old one or do we have to safely close/exit the original dialer?
For example say I did this:
dialer, err := t.Dialer(dialCtx, nil)
....
....
dialer, err := t.Dialer(dialCtx, newdialconf)
Does tor keep a state of the old dialer or is it now deleted and therefore okay to do this?
When running Tor Browser, attempting to browse a non existent onion service throws an afferent error code, such as 0xF0
with a description.
When using crez/bine, the Dialer response is "host unreachable" with no other explanation. Is it possible to retrieve the actual error code related to Tor's network or do I have to manually read it from exec's output?
When the network is enabled, first we give the command to do so https://github.com/cretz/bine/blob/master/tor/tor.go#L373 and only afterwards subscribe to the bootstrap events https://github.com/cretz/bine/blob/master/tor/tor.go#L381. There's a change bootstrap will finish before the subscribe, leading to a hang.
The bine dialer over here uses tor's Socks5ProxyUsername
and Socks5ProxyUsername
configuration parameters to authenticate with tor's SocksPort:
// Lookup proxy auth as needed
proxyAuth := conf.ProxyAuth
if proxyAuth == nil {
info, err := t.Control.GetConf("Socks5ProxyUsername", "Socks5ProxyPassword")
if err != nil {
return nil, err
}
if len(info) != 2 || info[0].Key != "Socks5ProxyUsername" || info[1].Key != "Socks5ProxyPassword" {
return nil, fmt.Errorf("Unable to get proxy auth")
}
proxyAuth = &proxy.Auth{User: info[0].Val, Password: info[1].Val}
}
if proxyAuth.User == "" && proxyAuth.Password == "" {
proxyAuth = nil
}
dialer, err := proxy.SOCKS5(proxyNetwork, proxyAddress, proxyAuth, conf.Forward)
This is incorrect usage of these parameters, as the SocksPort never requires authentication, and these parameters are used by tor to authenticate with an upstream proxy, to circumvent censhorship etc.
Excerpt from the tor manual:
Socks5Proxy host[:port]
Tor will make all OR connections through the SOCKS 5 proxy at host:port (or host:1080 if port is not specified).
Socks5ProxyUsername username
Socks5ProxyPassword password
If defined, authenticate to the SOCKS 5 server using username and password in accordance to RFC 1929. Both username and password must be between 1 and 255 characters.
Although incorrect, this should never result in an error, as the golang socks5 implementation also attempts an unauthenticated connection even if credentials are specified.
PR #32 is to address this.
On Windows when Bine is starting Tor it creates a permanent dos console window. This PR mostly hides it (there is a brief blink into existence for it and then it's hidden). Looks a lot nicer and other OSs like Linux do not have this issue of a terminal being opened for a Tor process
If I start an embedded tor process, you are currently starting it and immediately checking control port status https://github.com/cretz/bine/blob/master/tor/tor.go#L142:
err := tor.startProcess(ctx, conf)
// Connect the controller
if err == nil {
err = tor.connectController(ctx, conf)
}
this however is racey, because it's almost impossible for tor to start up fast enough for the control port to be open by the time you reach the check. If I explicitly add a couple second sleep before connect
, everything works nicely, otherwise starting just fails with Error on start: dial tcp 127.0.0.1:9051: connect: connection refused
.
Hello!
I've just tried using this with it's companion tor-static, but when building my go filem I recieved this error:
# github.com/cretz/bine/process/embedded/tor-0.3.5
../../../pkg/mod/github.com/cretz/[email protected]/process/embedded/tor-0.3.5/process.go:35:10: fatal error: tor_api.h: No such file or directory
35 | #include <tor_api.h>
| ^~~~~~~~~~~
compilation terminated.
It's probably just me being stupid, but any help would be appreciated. 😊
See https://trac.torproject.org/projects/tor/ticket/24204 and https://github.com/torproject/tor/blob/3507fead10ef4f990c0373f4405bd235c0f0b35c/src/feature/api/tor_api.h#L52-L62
It would be quite awesome if this leverages syscall.RawConn. More investigation needed.
What is the proper way to specify the SocksPort
to use?
If I do not specify at all then I assume the default port would be 9050
, but if I try to create a proxy client with that port like so:
config
conf := &tor.DialConf{Forward: proxy.Direct, ProxyAddress: "127.0.0.1:9050"}
I see in terminal:
output
socks connect tcp 127.0.0.1:9050->ipinfo.io:443: dial tcp 127.0.0.1:9050: connect: connection refused
If I omit the ProxyAddress
it works, but appears to assign the port randomly, different every time I start the program, and definitely not the typical default of 9050
:
output
Read line: 250-net/listeners/socks="127.0.0.1:34809"
...
Read line: 250-net/listeners/socks="127.0.0.1:36553"
...
etc etc
So then I have tried manually setting the SocksPort
, if I specify a TorrcFile
in the StartConf
through the logs it does seem to accept the file, but it is the same as above where it seems to ignore the SocksPort
defined in torrc
file and just assigns it randomly. Maybe it's ignoring the entire torrc
file or maybe that's not what that setting is for (it's unclear)?
torrc
SocksPort 9050
output
Read line: 250-net/listeners/socks="127.0.0.1:34809"
...
Read line: 250-net/listeners/socks="127.0.0.1:36553"
...
etc etc
The only way I have successfully assigned the SocksPort
has been through the use of the ExtraArgs
field in the StartConf
:
conf
ExtraArgs: []string{"--SocksPort", "9050"}
This does allow using the port that was specified, however it will then infinitely print out in terminal every minute:
output
Feb 16 07:15:18.000 [warn] Could not bind to 127.0.0.1:9050: Address already in use. Is Tor already running?
Feb 16 07:16:18.000 [warn] Could not bind to 127.0.0.1:9050: Address already in use. Is Tor already running?
Feb 16 07:17:18.000 [warn] Could not bind to 127.0.0.1:9050: Address already in use. Is Tor already running?
Feb 16 07:18:18.000 [warn] Could not bind to 127.0.0.1:9050: Address already in use. Is Tor already running?
Feb 16 07:19:18.000 [warn] Could not bind to 127.0.0.1:9050: Address already in use. Is Tor already running?
How should we properly specify the SocksPort
so that it works and doesn't break anything?
Consider putting at process/embedded/tor-0.3.5
. Then have a GeoIPFileReader func(ipv6 bool) (io.ReadCloser, error)
callback that can be passed to tor.Start
that, if present, will be used to fetch the geoip files and place them in the data dir, overridding if present, and set the GeoIPFile and/or GeoIPv6File start args. These args are not used and the file isn't loaded if the callback is present but returns nil with no error.
Is there a way to implement stream isolation in Bine?
For example say if we are using TorSocks and we want each request to potentially be a different exit node address we can simply change the username in the proxy URL.
func StreamIsolation() error {
// random integer
num := rand.Intn(0x7fffffff-10000) + 10000
// base url
proxybase := "socks5://%d:[email protected]:9050"
// proxy url with random credentials
proxyURL := fmt.Sprintf(proxybase, num)
// set proxy url
err := req.SetProxyUrl(proxyURL)
if err != nil {
return err
}
// check ip with aws
url := "https://checkip.amazonaws.com"
r, err := req.Get(url)
if err !=nil {
return err
}
return nil
}
Is there similar functionality in Bine?
If the node already has networking enabled - but has not yet finished building its circuits - EnableNetwork will abort at https://github.com/cretz/bine/blob/master/tor/tor.go#L370 even if wait
set set to true
. This might have unintended side effects for code that expects the circuits to be done, e.g. https://github.com/cretz/bine/blob/master/tor/listen.go#L259
hi,
I have been working on similar solution with tor, and found out
that several additional steps were required to get it done.
Im not a networking expert.
such as, upnp, local firewalls, vpn.
And to ensure everything is rightfully setup a pingpong service.
I understand those things might be out of context for this package,
however in this attempt to ease access to those capabilities
i believe those difficulties must also be tackled.
Otherwise many users will just fail.
As i said i m not a networking expert, however, i can use my facilities for testing if needed.
# github.com/cretz/bine/process/embedded/tor-0.3.5
go\src\github.com\cretz\bine\process\embedded\tor-0.3.5\process.go:35:10: fatal error: tor_api.h: No such file or directory
#include <tor_api.h>
^~~~~~~~~~~
compilation terminated.
When I run "go get github.com/cretz/bine/process/embedded", I got this error message.
I want to expose a local port to .onion
This is a feature request.
Would it be possible to support port maps like stem does in tor/listen.go
?
For example, in stem we can do:
service = controller.create_ephemeral_hidden_service({80: 5000, 90:5001}, await_publication = True)
This would yield two listeners, on ports 5000 and 5001, and it would map them to 80 and 90.
hs_desc_content event never triggers after calling GetHiddenServiceDescriptorAsync()
It looks like control/cmd_event:relayAsyncEvents(..) isn't parsing the event code correctly.
For HS_DESC_CONTENT events, when the function is trying to extract the eventcode, it grabs the whole first line of response.Data as the eventcode, which includes a bunch of other data, rather than just the eventcode at the start. This causes the issue as the event fails to match the one added by the listener function in eventWait.
To recreate issue :
package main
import (
"fmt"
"net/textproto"
"time"
"golang.org/x/net/context"
"github.com/cretz/bine/control"
)
func main() {
var conn, err = textproto.Dial("tcp", "localhost:9052")
if err != nil {
fmt.Println("dial error:", err)
return
}
defer conn.Close()
var controller = control.NewConn(conn)
if err := controller.Authenticate(""); err != nil {
fmt.Println("authentication error: ", err)
return
}
fmt.Println("Authenticated!")
go func() {
time.Sleep(time.Second * 2)
err = controller.GetHiddenServiceDescriptorAsync("<SomeOnionAddress>", "")
if err != nil {
fmt.Println("GetHiddenServiceDescriptorAsync error: ", err)
return
}
fmt.Println("Request Sent!")
}()
_, err = controller.EventWait(context.Background(), []control.EventCode{control.EventCodeHSDesc, control.EventCodeHSDescContent},
func(evt control.Event) (bool, error) {
hs, _ := evt.(*control.HSDescContentEvent)
if hs != nil {
fmt.Printf("main: <hsdesc content>: %v\n", hs)
}
return false, nil
})
}
The previous code should print out a descriptor.
Leaving this here for future discussion. If you're up to receiving the patch, I might hash this out sometime soon or after the new Transport
definition lands. libp2p
aims to be a generally-useful networking library and having a tor transport would be a boon! The process could also simplify bine usage 😄
Hi,
i written an alternate compatible embedded process that does not rely on building from sources.
Instead it builds directly from the tarballs available from the website.
https://github.com/clementauger/tor-prebuilt
To start the tor process it extract the assets on disk then simply start the process as a regular file.
i did not extensively tested it, but the main.go taken from your example folder did work, so i guess its a starting point.
thanks for the original api and ideas.
Hi,
I'm building docker containers, wasn't so keen on having go-libtor embedded, or having alpine's apk install it.
I've created a tor-proxy on the same docker network, and was wondering if it's possible to point to that container?
cat docker-compose.yml
version: "3.3"
services:
torproxy:
restart: always
image: dperson/torproxy:latest
restart: always
networks:
- "net"
ports:
- "9050:9050" # Tor proxy
- "9051:9051" # Tor control port
- "8118:8118" # Privoxy
networks:
net:
external: true
Cheers
Chris
How to persist an onion ID from a generated private key?
Key is generated by Shallot and imported:
buff, _ := ioutil.ReadFile("mytor/private_key")
block, _ := pem.Decode(buff)
key, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
cfg := &tor.ListenConf{
Key: key,
}
But onion id always change on each restart.
Basically need to have a different package for each semi-major Tor version
Is it possible to change the length of onion ID that we get, i.e. can ask for greater sized onion ID that we get from the following code?
onion, err := t.Listen(listenCtx, &tor.ListenConf{Version3: true, RemotePorts: []int{80}})
Hello, I have searched the Bine API to see how I can get circuits information Tor currently has available, without any success. The main page of Bine (https://github.com/cretz/bine) mentions that Bine is similar to Stem. In Stem, we can circuits information with controller.get_circuits()
(https://stem.torproject.org/tutorials/examples/list_circuits.html), but this method is not available in Bine as a function. Maybe, I just don't look right in the API or something like that.
My question is: How can we get circuits information Tor currently has available with Bine? I hope someone can help me.
hi,
i am struggling using the torutil ed25519 api to store and reload a keypair to a file.
I can at worst, store both parts as raw byte sequence to different files, but i dont see how to forge a keypair back (...). any idea ? ideally, can i pem encode it anyhow ?
I'm not sure whats the issue but i assume its something to do with missing c libraries
/usr/bin/ld: cannot find -ltor-app
/usr/bin/ld: cannot find -ltor-compress
/usr/bin/ld: cannot find -ltor-evloop
/usr/bin/ld: cannot find -ltor-tls
/usr/bin/ld: cannot find -ltor-crypt-ops
/usr/bin/ld: cannot find -lcurve25519_donna
/usr/bin/ld: cannot find -ltor-geoip
/usr/bin/ld: cannot find -ltor-process
/usr/bin/ld: cannot find -ltor-time
/usr/bin/ld: cannot find -ltor-fs
/usr/bin/ld: cannot find -ltor-encoding
/usr/bin/ld: cannot find -ltor-sandbox
/usr/bin/ld: cannot find -ltor-container
/usr/bin/ld: cannot find -ltor-net
/usr/bin/ld: cannot find -ltor-thread
/usr/bin/ld: cannot find -ltor-memarea
/usr/bin/ld: cannot find -ltor-math
/usr/bin/ld: cannot find -ltor-meminfo
/usr/bin/ld: cannot find -ltor-osinfo
/usr/bin/ld: cannot find -ltor-log
/usr/bin/ld: cannot find -ltor-lock
/usr/bin/ld: cannot find -ltor-fdio
/usr/bin/ld: cannot find -ltor-string
/usr/bin/ld: cannot find -ltor-term
/usr/bin/ld: cannot find -ltor-smartlist-core
/usr/bin/ld: cannot find -ltor-malloc
/usr/bin/ld: cannot find -ltor-wallclock
/usr/bin/ld: cannot find -ltor-err
/usr/bin/ld: cannot find -ltor-intmath
/usr/bin/ld: cannot find -ltor-ctime
/usr/bin/ld: cannot find -ltor-trace
/usr/bin/ld: cannot find -lkeccak-tiny
/usr/bin/ld: cannot find -led25519_ref10
/usr/bin/ld: cannot find -led25519_donna
/usr/bin/ld: cannot find -lor-trunnel
/usr/bin/ld: cannot find -levent
/usr/bin/ld: cannot find -llzma
collect2: error: ld returned 1 exit status
Hey there!
I'm playing around with a hobby project in my spare time. For now I'm just building and evaluating the tech stack I'd like to build on top, and Tor came up as one of the components I'd like to pursue more seriously. At least in the initial experimentation phase.
I've looked around for Tor libraries in Go, and I think yours comes closest to a easily usable one, though I'll admit I haven't used it much yet. My primary concern was that by default you required the existence of a Tor process on the host machine. This imho limits the usage of your library to a very narrow group of people.
Before you object, I did see that you have an embeddable version of Tor that people can clone, build manually and then link against from this project. While it's a bit better, I don't think it expands your user base much, since the manual build step breaks all Go workflows. I.e. I cannot build my project on top of yours, because I cannot afford an extra build step (my primary target is mobile).
Left out in the cold, I started looking into how I could create a truly self-contained Go library out of Tor. It took an annoyingly long time because of various limitations of Go and CGO, but after a few weeks I ended up with a seemingly working solution (https://github.com/ipsn/go-libtor). Currently it builds on Linux amd64, 386, arm64 and arm (libc + musl); and Android amd64, 386, arm64 and arm. I don't think it would be too hard to add support for osx + windows, but those aren't really my priorities currently.
A nice design of the project is that it auto-updates every night via Travis cron jobs to the latest stable OpenSSL + Tor upstream projects, so hopefully it won't take constant effort to maintain. I'm sure there are a few rough edges in store but my question is whether you'd be interested in me submitting a PR to add direct support in your lib for my external lib?
API wise I made it fully compatible with your repo, and also written up process.Creator/Process
wrapper based demo to highlight that it's fully cross compatible https://github.com/ipsn/go-libtor#usage. I can submit a PR to upstream the wrappers into your library if you'd be interested. Alternatively I can create the wrappers in my project too to have the same effect, but I thought yours might be a bit more appropriate coupling point. Tell me what you think.
Cheers
Peter
After some fuzzing I've found this hang after sending following data form tor to bine controller conn:
250-AUTH METHODS=SAFECOOKIE COOKIEFILE="/dev/random"
250
Seems like there is just ioutil that reads(ioutil.readAll) any file on fs and sends back to tor if its length is equal to 32 bytes
...
io/ioutil.ReadFile(0xc00044a7d0, 0xb, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/golang/src/io/ioutil/ioutil.go:73 +0x154
github.com/ThePrzeglo/sdamp/vendor/github.com/cretz/bine/control.(*Conn).Authenticate(0xc000380cd0, 0x0, 0x0, 0x1, 0xc000046ea8)
/fuzzing/vendor/github.com/cretz/bine/control/cmd_authenticate.go:34 +0x2ad
...
It isn't critical bug nevertheless I do not consider it as a feature.
Fuzzer code(note: might not be the best, I didn't look at coverage)
import (
"bytes"
"io"
"net/textproto"
"unicode/utf8"
"github.com/cretz/bine/control"
)
type NopWriter struct {
io.Reader
}
func (*NopWriter) Write(b []byte) (int, error) {
return len(b), nil
}
func (*NopWriter) Close() error {
return nil
}
func Fuzz(data []byte) int {
if !utf8.Valid(data) {
return -1
}
r := bytes.NewReader(data)
rw := &NopWriter{Reader: r}
tr := textproto.NewConn(rw)
c := control.NewConn(tr)
c.Authenticate("") // Crashed here
c.ReadResponse()
c.GetHiddenServiceDescriptorAsync("addr", "srv")
c.ReadResponse()
c.GetConf("confval1")
c.ReadResponse()
c.RedirectStream("asdf", "asdf", 123)
c.ReadResponse()
if _, err := c.GetConf("DisableNetwork"); err != nil {
return 0
}
if err := c.SetConf(control.KeyVals("DisableNetwork", "0")...); err != nil {
return 0
}
err := c.DelOnion("SVCID")
if err != nil {
return 0
}
err = c.DropGuards()
if err != nil {
return 0
}
return 0
}
This library currently supports starting Tor offline and then enabling networking at a later point. Sometimes it can be useful to also disable networking. Perhaps you could add an equivalent method?
My initial approach was to tear down Tor when not needed and rebuild it when needed agan, unfortunately something goes haywire in the process after tear-down and I can't rebuild onions post-restart. If I restart my process, everything works again. I've received similar bugreports on my lib too and I tried Tor 0.4.2.7 and it hung the same way.
See cretz/tor-static#7 and this mailing list post. We'll have to change the process/embedded/process.go
's LDFLAGS
. While the email mentions using a call to determine the static libs, we're obviously still gonna hard code them, though we could use a code generator to generate that. I doubt that it's that big of a deal. If we start finding this list is more and more volatile, I might make multiple embedded
versions the support different Tor versions.
First of all, thank you for Bine! I love it so far and I'm using it to learn more Go.
Anyway, I stumble upon a problem when using the dialer in multiple routines. Sometimes I can run it for a long period without any issues. I wonder if you might have any idea what's going wrong.
I'm setting up the dialer once in main.go and provide each worker with it.
goroutine 820 [select]:
github.com/cretz/bine/tor.(*Dialer).DialContext(0xc000101270, 0x4716ce0, 0xc00010a000, 0x469fdc7, 0x3, 0xc000422730, 0x42, 0x60, 0x4c3a4a0, 0x118, ...)
/Users/sebwes/src/go/pkg/mod/github.com/cretz/[email protected]/tor/dialer.go:107 +0x1ea
net/http.(*Transport).dial(0xc000156a00, 0x4716ce0, 0xc00010a000, 0x469fdc7, 0x3, 0xc000422730, 0x42, 0x0, 0xc00011c500, 0x0, ...)
/usr/local/Cellar/go/1.15.5/libexec/src/net/http/transport.go:1141 +0x1fd
net/http.(*Transport).dialConn(0xc000156a00, 0x4716ce0, 0xc00010a000, 0x0, 0xc0005fe5f0, 0x5, 0xc000422730, 0x42, 0x0, 0xc000217560, ...)
/usr/local/Cellar/go/1.15.5/libexec/src/net/http/transport.go:1575 +0x1abb
net/http.(*Transport).dialConnFor(0xc000156a00, 0xc000394840)
/usr/local/Cellar/go/1.15.5/libexec/src/net/http/transport.go:1421 +0xc6
created by net/http.(*Transport).queueForDial
/usr/local/Cellar/go/1.15.5/libexec/src/net/http/transport.go:1390 +0x40f
goroutine 821 [IO wait]:
internal/poll.runtime_pollWait(0xb491660, 0x72, 0x4711680)
/usr/local/Cellar/go/1.15.5/libexec/src/runtime/netpoll.go:222 +0x55
internal/poll.(*pollDesc).wait(0xc0000ddb98, 0x72, 0x4711600, 0x49a0f90, 0x0)
/usr/local/Cellar/go/1.15.5/libexec/src/internal/poll/fd_poll_runtime.go:87 +0x45
internal/poll.(*pollDesc).waitRead(...)
/usr/local/Cellar/go/1.15.5/libexec/src/internal/poll/fd_poll_runtime.go:92
internal/poll.(*FD).Read(0xc0000ddb80, 0xc0002da750, 0x4, 0x90, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.15.5/libexec/src/internal/poll/fd_unix.go:159 +0x1a5
net.(*netFD).Read(0xc0000ddb80, 0xc0002da750, 0x4, 0x90, 0x45, 0x0, 0x0)
/usr/local/Cellar/go/1.15.5/libexec/src/net/fd_posix.go:55 +0x4f
net.(*conn).Read(0xc0000d4220, 0xc0002da750, 0x4, 0x90, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.15.5/libexec/src/net/net.go:182 +0x8e
io.ReadAtLeast(0xb4180d8, 0xc0000d4220, 0xc0002da750, 0x4, 0x90, 0x4, 0x0, 0x90, 0x0)
/usr/local/Cellar/go/1.15.5/libexec/src/io/io.go:314 +0x87
io.ReadFull(...)
/usr/local/Cellar/go/1.15.5/libexec/src/io/io.go:333
golang.org/x/net/internal/socks.(*Dialer).connect(0xc0001227d0, 0x4716ce0, 0xc00010a000, 0x4718e20, 0xc0000d4220, 0xc000422730, 0x42, 0x0, 0x0, 0x0, ...)
/Users/sebwes/src/go/pkg/mod/golang.org/x/[email protected]/internal/socks/client.go:109 +0x738
golang.org/x/net/internal/socks.(*Dialer).DialWithConn(0xc0001227d0, 0x4716ce0, 0xc00010a000, 0x4718e20, 0xc0000d4220, 0x469fdc7, 0x3, 0xc000422730, 0x42, 0x0, ...)
/Users/sebwes/src/go/pkg/mod/golang.org/x/[email protected]/internal/socks/socks.go:196 +0xec
golang.org/x/net/internal/socks.(*Dialer).Dial(0xc0001227d0, 0x469fdc7, 0x3, 0xc000422730, 0x42, 0x100000000000000, 0x0, 0x0, 0x0)
/Users/sebwes/src/go/pkg/mod/golang.org/x/[email protected]/internal/socks/socks.go:226 +0x396
github.com/cretz/bine/tor.(*Dialer).DialContext.func1(0xc000101270, 0x469fdc7, 0x3, 0xc000422730, 0x42, 0xc0006a48a0, 0x4716ce0, 0xc00010a000, 0xc0006a4900)
/Users/sebwes/src/go/pkg/mod/github.com/cretz/[email protected]/tor/dialer.go:99 +0x7b
created by github.com/cretz/bine/tor.(*Dialer).DialContext
/Users/sebwes/src/go/pkg/mod/github.com/cretz/[email protected]/tor/dialer.go:98 +0xfa
Happy for any input :)
Is it possible to use Tor bridges such as obfs4 and meek?
Building on cretz/tor-static#1, I don't have a mac and so am wanting anyone who is willing to to make sure that this works on macOS with embedded (i.e. statically linked Tor). The embeddedversion
and embeddedfilesystem
examples should be enough to test with.
When starting an onion Listener, the library first requests the onion to be created, and only later does it start listening for events (https://github.com/cretz/bine/blob/master/tor/listen.go#L267). There's a chance that by the time it subscribes to events, listening has already been started (or failed). This will start Listen to hang.
I'm not sure if this is the issue I'm hitting in my project or not, but if I restart my Tor node and recreate an old onion, it almost always hangs.
Just need to run integration tests against that version. If changing default embedded version, need to wait on cretz/tor-static#16 first.
Requires:
process/embedded
Unfortunately, we have a Version3
boolean in ListenConf
that defaults to false even though new Tor wants v3 by default. Not really a big deal, just need to make it clear that it has to be specified explicitly. If v2 is ever deprecated, we'll deprecate the option.
The context here is an application that publishes an onion service, but the user closes the app while everything is still being initialized. I want to close things down as gracefully as possible in that situation.
If tor.Start
has already returned and we've got a reference to a *Tor
we can Close()
it, but if t.Listen
has not returned yet, we don't have an *OnionService
we can Close()
first, even though we're in the process of publishing one. So we try to t.Close()
while the onion service is still being published and occasionally we see:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7ae17e]
goroutine 8 [running]:
github.com/cretz/bine/control.(*Conn).debugEnabled(...)
/home/hkparker/Development/Go/pkg/mod/github.com/cretz/[email protected]/control/conn.go:91
github.com/cretz/bine/control.(*Conn).SendRequest(0x0, {0x1018d1c, 0xc00038b6c0}, {0xc00038b718, 0xc00038b728, 0x1})
/home/hkparker/Development/Go/pkg/mod/github.com/cretz/[email protected]/control/conn.go:56 +0x5e
github.com/cretz/bine/control.(*Conn).sendRequestIgnoreResponse(...)
/home/hkparker/Development/Go/pkg/mod/github.com/cretz/[email protected]/control/conn.go:47
github.com/cretz/bine/control.(*Conn).DelOnion(...)
/home/hkparker/Development/Go/pkg/mod/github.com/cretz/[email protected]/control/cmd_onion.go:200
github.com/cretz/bine/tor.(*OnionService).Close(0xc00019e310)
/home/hkparker/Development/Go/pkg/mod/github.com/cretz/[email protected]/tor/listen.go:325 +0x13b
github.com/cretz/bine/tor.(*Tor).Listen(0xc0003c6000, {0x114e930, 0xc00013c000}, 0xc00038bb78)
/home/hkparker/Development/Go/pkg/mod/github.com/cretz/[email protected]/tor/listen.go:291 +0x141e
...
I tried using a cancelable context passed into t.Listen
, and calling the cancel function before closing tor, but that hung for reasons unknown.
I think what's going on here is that (*Tor).Close
assigns the control socket to nil, then somewhere in (*Tor).Listen
there's an error, which at the end, results in an attempt to close the onion service. But by this point tor is closed and the control port is nil, so the onion service's closer is probably hitting the nil pointer dereference here. I thought about just PRing a nil check there, however I noticed there were other calls in the (*Tor).Listen
function that might have issues.
So maybe the actual solution here is just to not assign the control port to nil, and just let all the other calls check and early return on "use of closed connection" errors. That's probably the most concurrency safe option, but I wanted to discuss it a little before submitting a PR. Alternatively I suppose the cancel function should really be what's used, and perhaps that's what I need to fix (potentially user error, I didn't spend to long on it) and a panic when t.Listen
isn't canceled properly is expected.
Let me know what you make of this and if there's anything you'd like me to submit.
At least need an example showing it, if not helpers to make it easy.
Basically, show a simple example of doing what Cloudflare does at https://blog.cloudflare.com/cloudflare-onion-service/
Now that golang/go#24331 landed, have a Windows version that creates a syscall.RawConn
from the socket and implement the rest of net.Conn
w/ dummy stuff. Also update the README and package docs.
We often spin up multiple onions at one time
(in app, when loading multiple identities at once, in integ test. again, 1 server and 3 peers are created at once)
currently there is only support for waiting for full online status inline, at creation time with the call to Listen.
It would be nice if that code was pulled out and made an callable function, so we could init N onions, and then wait on all of them at once.
I'm not sure if there's anyway to make this a status like tors GetInfo of bootstrap startup phase, but that might be even more ideal, because our end goal is a GUI that just updates status icons of different parts, such as each Identity's coming online status. This may not be possible, that's fine
linux 4.19, tor 0.4.0.5.
I was trying to run the example client code to create communicating hidden services, but i couldn't get the example code to run on my manjaro linux.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x63cf53]
goroutine 24 [running]:
golang.org/x/net/proxy.(*socks5).Dial(0xc00009ec30, 0x6f2455, 0x3, 0xc0000966a0, 0xf, 0xf, 0x0, 0x28a, 0x0)
/home/h/go/src/golang.org/x/net/proxy/socks5.go:71 +0x63
github.com/cretz/bine/tor.(*Dialer).DialContext.func1(0xc000085180, 0x6f2455, 0x3, 0xc0000966a0, 0xf, 0xc00009aa80, 0x754200, 0xc000096010, 0xc00009aae0)
/home/h/go/src/github.com/cretz/bine/tor/dialer.go:95 +0x7e
created by github.com/cretz/bine/tor.(*Dialer).DialContext
/home/h/go/src/github.com/cretz/bine/tor/dialer.go:94 +0xfa
exit status 2
the code was:
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/cretz/bine/tor"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
// Start tor with default config (can set start conf's DebugWriter to os.Stdout for debug logs)
fmt.Println("Starting tor and fetching title of https://eludemaillhqfkh5.onion, please wait a few seconds...")
t, err := tor.Start(nil, nil)
if err != nil {
return err
}
defer t.Close()
// Wait at most a minute to start network and get
dialCtx, dialCancel := context.WithTimeout(context.Background(), time.Minute)
defer dialCancel()
// Make connection
dialer, err := t.Dialer(dialCtx, nil)
if err != nil {
return err
}
httpClient := &http.Client{Transport: &http.Transport{DialContext: dialer.DialContext}}
// Get /
resp, err := httpClient.Get("https://example.com")
if err != nil {
return err
}
defer resp.Body.Close()
if err != nil {
return err
}
bodyBytes, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(bodyBytes))
return nil
}
A slight variation on the example client.
To be fair I'm guessing this isn't really feasible but I figured I'd ask.
Accepting a connection from a hidden service gives you a connection from Tor to your local listener (by default, this will be 127.0.0.1:something
. However, it would be super convenient for me if RemoteAddr
returned the actual onion ID of the client.
I'm no Tor protocol expert but necessarily this information exists somewhere in Tor. The fact that we're proxying through a local TCP socket (and the connection we get is just that socket) makes that information inaccessible to the user. If it's possible to query Tor for this information (perhaps via Tor's source port for the connection its dialing to the local listener), we could then create our own net.Conn
that provides this info up to the user.
Not sure where to start here but I will go looking. Would appreciate some additional context if anyone has any, happy to PR this if I can figure out a path forward.
Hello, any good way/example in how to plug chromedp to this?
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.