Files
i2p.plugins.tor-updater/main.go

335 lines
10 KiB
Go
Raw Normal View History

package main
2022-01-16 14:45:43 -05:00
import (
2022-01-23 12:00:37 -05:00
"embed"
2022-01-16 14:45:43 -05:00
"flag"
2022-02-07 21:38:54 -05:00
"fmt"
2022-01-16 14:45:43 -05:00
"log"
"os"
2022-03-04 01:22:39 -05:00
"os/signal"
"path/filepath"
"runtime"
2022-01-16 14:45:43 -05:00
2022-01-16 15:33:47 -05:00
"github.com/cloudfoundry/jibber_jabber"
i2cpcheck "github.com/eyedeekay/checki2cp"
2022-02-08 18:31:32 -05:00
"github.com/itchio/damage"
"github.com/itchio/damage/hdiutil"
"github.com/itchio/headway/state"
tbget "i2pgit.org/idk/i2p.plugins.tor-manager/get"
tbserve "i2pgit.org/idk/i2p.plugins.tor-manager/serve"
"github.com/eyedeekay/go-I2P-jpackage"
2022-01-16 14:45:43 -05:00
)
2022-02-07 21:09:43 -05:00
/*
TODO: A "Default" config file which uses hardened Tor Browser for clearnet
(or default-route) browsing.
*/
2022-01-23 12:00:37 -05:00
//go:embed tor-browser/unpack/i2p.firefox/*
2022-02-06 16:57:30 -05:00
//go:embed tor-browser/unpack/i2p.firefox.config/*
//go:embed tor-browser/unpack/awo@eyedeekay.github.io.xpi
//go:embed tor-browser/TPO-signing-key.pub
2022-01-28 00:09:18 -05:00
//go:embed garliconion.png
//go:embed onion.png
//go:embed torbrowser.desktop
//go:embed i2ptorbrowser.desktop
2022-01-23 12:00:37 -05:00
var content embed.FS
func OS() string {
switch runtime.GOOS {
case "darwin":
2022-02-08 01:23:30 -05:00
return "osx"
case "linux":
return "linux"
case "windows":
return "win"
default:
return "unknown"
}
}
func ARCH() string {
switch runtime.GOARCH {
case "386":
return "32"
case "amd64":
return "64"
case "arm64":
if OS() == "osx" {
return "64"
}
return ""
default:
return "unknown"
}
}
2022-01-16 21:22:04 -05:00
2022-01-16 14:45:43 -05:00
var (
2022-01-23 11:42:23 -05:00
lang = flag.String("lang", "", "Language to download")
system = flag.String("os", OS(), "OS/arch to download")
arch = flag.String("arch", ARCH(), "OS/arch to download")
2022-01-23 11:42:23 -05:00
i2pbrowser = flag.Bool("i2pbrowser", false, "Open I2P in Tor Browser")
2022-02-06 16:57:30 -05:00
i2pconfig = flag.Bool("i2pconfig", false, "Open I2P routerconsole in Tor Browser with javscript enabled and non-routerconsole sites disabled")
2022-01-23 11:42:23 -05:00
torbrowser = flag.Bool("torbrowser", false, "Open Tor Browser")
2022-01-27 22:41:30 -05:00
verbose = flag.Bool("verbose", false, "Verbose output")
directory = flag.String("directory", DefaultDir(), "Directory operate in")
host = flag.String("host", "127.0.0.1", "Host to serve on")
port = flag.Int("port", 7695, "Port to serve on")
bemirror = flag.Bool("bemirror", false, "Act as an in-I2P mirror when you're done downloading")
shortcuts = flag.Bool("shortcuts", false, "Create desktop shortcuts")
apparmor = flag.Bool("apparmor", false, "Generate apparmor rules")
2022-02-10 23:39:31 -05:00
offline = flag.Bool("offline", false, "Work offline. Differs from Firefox's offline mode in that cannot be disabled until the browser is closed.")
clearnet = flag.Bool("clearnet", false, "Use clearnet (no Tor or I2P)")
profile = flag.String("profile", "", "use a custom profile path, normally blank")
help = flag.Bool("help", false, "Print help")
2022-02-22 22:12:25 -05:00
/* TODO: Hash sometimes doesn't match when downloading from this mirror. Probably due to latency
between updates. Know for sure why before enabling it.*/
//mirror = flag.String("mirror", "http://dist.torproject.i2p/torbrowser/", "Mirror to use(I2P)")
2022-02-22 22:12:25 -05:00
/* TODO: This is a clearnet mirror which was originally used by default. Since this is intended as
an I2P browser configurer, and we guarantee the availability of the HTTP proxy by starting our own
if one is unavailable, we download over I2P instead. This is pretty fast these days really, but for
77 or so MB it's noticably delayed still. In "clearnet" modes, it might make sense to default to
this mirror instead of the I2P one, or maybe offer a convenience option for just the download.*/
mirror = flag.String("mirror", "https://dist.torproject.org/torbrowser/", "Mirror to use")
solidarity = flag.Bool("onion", false, "Serve an onion site which shows some I2P propaganda")
2022-02-25 00:30:41 -05:00
torrent = flag.Bool("torrent", tbget.TorrentReady(), "Create a torrent of the downloaded files and seed it over I2P using an Open Tracker")
2022-03-03 23:48:32 -05:00
destruct = flag.Bool("destruct", false, "Destructively delete the working directory when finished")
2022-03-04 12:40:25 -05:00
password = flag.String("password", Password(), "Password to encrypt the working directory with. Implies -destruct, only the encrypted container will be saved.")
chat = flag.Bool("chat", false, "Open a WebChat client")
2022-02-10 23:39:31 -05:00
/*ptop = flag.Bool("p2p", false, "Use bittorrent over I2P to download the initial copy of Tor Browser")*/
2022-01-16 14:45:43 -05:00
)
var snowflake *bool
var client *tbserve.Client
func main() {
filename := filepath.Base(os.Args[0])
SnowflakeFlag()
2022-02-07 21:09:43 -05:00
usage := flag.Usage
flag.Usage = func() {
2022-02-07 21:38:54 -05:00
fmt.Printf("Usage: %s %s\n", filename, "[options]")
fmt.Printf("\n")
fmt.Printf("Downloads, verifies and unpacks Tor Browser. Manages the Tor Browser\n")
fmt.Printf("system in environments where Tor is not in use.\n")
fmt.Printf("\n")
fmt.Printf("Options:\n")
fmt.Printf("\n")
2022-02-07 21:09:43 -05:00
usage()
}
2022-01-16 14:45:43 -05:00
flag.Parse()
if *password != "" {
log.Println("Looking for directory with password")
DecryptTarXZifThere(*directory, *password)
2022-03-04 01:22:39 -05:00
// capture sigint
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for range c {
log.Println("Caught interrupt, exiting")
2022-03-04 12:40:25 -05:00
err := EncryptTarXZip(*directory, *password)
if err != nil {
log.Println(err)
}
os.Exit(0)
2022-03-04 01:22:39 -05:00
}
}()
}
2022-03-05 00:08:13 -05:00
if *clearnet {
*mirror = "http://dist.torproject.org/torbrowser/"
}
if *snowflake {
go Snowflake()
}
if *destruct {
defer OverwriteDirectoryContents(*directory)
}
tbget.WORKING_DIR = *directory
if filename == "i2pbrowser" {
log.Println("Starting I2P in Tor Browser")
*i2pbrowser = true
} else if filename == "torbrowser" {
log.Println("Starting Tor Browser")
*torbrowser = true
2022-02-07 21:09:43 -05:00
} else if filename == "i2pconfig" {
log.Println("Starting I2P routerconsole in Tor Browser")
*i2pconfig = true
} else if filename == "firefox" || *clearnet || *offline {
*clearnet = true
2022-02-14 23:42:08 -05:00
}
if *profile == "" {
if *offline {
*profile = filepath.Join(tbget.WORKING_DIR, "profile.firefox.offline")
} else if *clearnet {
*profile = filepath.Join(tbget.WORKING_DIR, "profile.firefox")
} else {
2022-02-14 23:42:08 -05:00
*profile = filepath.Join(tbget.WORKING_DIR, "profile.firefox.default")
2022-02-07 21:09:43 -05:00
}
2022-02-14 23:42:08 -05:00
} else {
*profile = filepath.Join(tbget.WORKING_DIR, *profile)
}
if *i2pbrowser && *torbrowser {
2022-01-23 11:42:23 -05:00
log.Fatal("Please don't open I2P and Tor Browser at the same time when running from the terminal.")
}
2022-01-16 15:33:47 -05:00
if *lang == "" {
var err error
*lang, err = jibber_jabber.DetectIETF()
if err != nil {
log.Fatal("Please specify a language", err)
}
log.Println("Using auto-detected language", *lang)
}
2022-02-20 00:05:57 -05:00
if tbget.TestHTTPDefaultProxy() {
log.Println("I2P HTTP proxy OK")
} else {
log.Println("I2P HTTP proxy not OK")
run, err := i2cpcheck.ConditionallyLaunchI2P()
if err != nil {
log.Println("Couldn't launch I2P", err)
}
if run {
if tbget.TestHTTPDefaultProxy() {
log.Println("I2P HTTP proxy OK after launching I2P")
} else {
go proxy()
if !tbget.TestHTTPBackupProxy() {
log.Fatal("Please set the I2P HTTP proxy on localhost:4444", err)
}
}
} else {
2022-02-20 00:05:57 -05:00
I2Pdaemon, err := I2P.NewDaemon(*directory, false)
if err != nil {
2022-02-20 00:05:57 -05:00
log.Println(err)
return
}
2022-02-20 00:05:57 -05:00
if err = I2Pdaemon.Start(); err != nil {
log.Fatal(err)
}
shutdown = true
defer I2Pdaemon.Stop()
go runSysTray(true)
if tbget.TestHTTPDefaultProxy() {
log.Println("I2P HTTP proxy OK")
} else {
2022-02-20 00:05:57 -05:00
log.Fatal("Embedded i2pd unable to start")
}
}
}
2022-02-20 00:05:57 -05:00
var err error
client, err = tbserve.NewClient(*verbose, *lang, *system, *arch, *mirror, &content)
if err != nil {
log.Fatal("Couldn't create client", err)
}
if *apparmor {
err := GenerateAppArmor()
if err != nil {
log.Fatal("Couldn't generate apparmor rules", err)
}
log.Println("################################################################")
log.Println("# AppArmor rules generated successfully #")
log.Println("################################################################")
log.Println("!IMPORTANT! You must now run the following commands:")
log.Println("sudo mkdir -p /etc/apparmor.d/tunables/")
log.Println("sudo cp tunables.torbrowser.apparmor /etc/apparmor.d/tunables/torbrowser")
log.Println("sudo cp torbrowser.Tor.tor.apparmor /etc/apparmor.d/torbrowser.Tor.tor")
log.Println("sudo cp torbrowser.Browser.firefox.apparmor /etc/apparmor.d/torbrowser.Browser.firefox")
log.Println("sudo apparmor_parser -r /etc/apparmor.d/tunables/torbrowser")
log.Println("sudo apparmor_parser -r /etc/apparmor.d/torbrowser.Tor.tor")
log.Println("sudo apparmor_parser -r /etc/apparmor.d/torbrowser.Browser.firefox")
log.Println("To copy them to apparmor profiles directory and reload AppArmor")
return
}
if *shortcuts {
err := CreateShortcuts()
if err != nil {
log.Fatal("Couldn't create desktop shortcuts", err)
}
}
client.Host = *host
client.Port = *port
2022-01-23 12:00:37 -05:00
client.TBS.Profile = &content
2022-02-06 16:57:30 -05:00
client.TBS.PassThroughArgs = flag.Args()
2022-03-01 00:17:59 -05:00
if runtime.GOOS == "darwin" {
2022-02-21 18:08:49 -05:00
consumer := &state.Consumer{
OnMessage: func(lvl string, msg string) {
log.Printf("[%s] %s", lvl, msg)
},
}
host := hdiutil.NewHost(consumer)
defer damage.Unmount(host, client.TBD.BrowserDir())
2022-02-08 18:31:32 -05:00
}
2022-02-06 16:57:30 -05:00
// log.Fatalf("%s", client.TBS.PassThroughArgs)
if *help {
flag.Usage()
if err := client.TBS.RunTBHelpWithLang(); err != nil {
log.Fatal(err)
}
return
}
client.TBS.UnpackI2PAppData()
client.TBS.UnpackI2PData()
if *torrent {
log.Println("Generating I2P torrents of Tor packages")
if err := client.TBD.GenerateMissingTorrents(); err != nil {
log.Fatal(err)
}
}
2022-02-28 19:59:47 -05:00
client.TBS.RunTorWithLang()
if *chat {
log.Println("Starting I2P chat")
go BRBClient(*directory, "brb")
}
2022-02-14 23:42:08 -05:00
if *i2pbrowser {
if err := client.TBS.RunI2PBWithLang(); err != nil {
2022-02-08 18:31:32 -05:00
log.Fatal(err)
}
2022-02-06 16:57:30 -05:00
} else if *i2pconfig {
if err := client.TBS.RunI2PBAppWithLang(); err != nil {
2022-02-08 18:31:32 -05:00
log.Fatal(err)
}
2022-01-23 11:42:23 -05:00
} else if *torbrowser {
2022-02-08 18:31:32 -05:00
if err := client.TBS.RunTBWithLang(); err != nil {
log.Fatal(err)
}
2022-02-14 23:42:08 -05:00
} else if *offline {
log.Println("Working offline")
if err := client.TBS.RunTBBWithOfflineClearnetProfile(*profile, *offline, *clearnet); err != nil {
log.Fatal(err)
}
} else if *clearnet {
log.Println("Using a custom profile")
if err := client.TBS.RunTBBWithOfflineClearnetProfile(*profile, *offline, *clearnet); err != nil {
log.Fatal(err)
}
2022-01-23 11:42:23 -05:00
} else {
if *bemirror {
go client.TBD.Serve()
}
2022-02-28 19:59:47 -05:00
if *solidarity {
2022-02-28 21:15:35 -05:00
client.Onion.UnpackSite()
go func() {
if err := client.Onion.ListenAndServe(); err != nil {
log.Println("Onion error:", err)
}
}()
2022-02-28 19:59:47 -05:00
}
2022-02-14 23:42:08 -05:00
go runSysTray(false)
2022-01-23 11:42:23 -05:00
if err := client.Serve(); err != nil {
log.Fatal(err)
}
2022-01-16 21:22:04 -05:00
}
}
func pathToMe() (string, error) {
ex, err := os.Executable()
if err != nil {
return "", err
}
exPath, err := filepath.Abs(ex)
if err != nil {
return "", err
}
return exPath, nil
}