2019-05-11 00:43:46 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"flag"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
2019-08-14 19:19:28 -04:00
|
|
|
"strconv"
|
2019-05-11 00:43:46 -04:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crawshaw.io/littleboss"
|
|
|
|
"github.com/eyedeekay/sam-forwarder/config"
|
2019-08-14 19:05:58 -04:00
|
|
|
"github.com/eyedeekay/sam-forwarder/hashhash"
|
2019-05-11 00:43:46 -04:00
|
|
|
"github.com/eyedeekay/sam-forwarder/manager"
|
|
|
|
)
|
|
|
|
|
|
|
|
type flagOpts []string
|
|
|
|
|
|
|
|
func (f *flagOpts) String() string {
|
|
|
|
r := ""
|
|
|
|
for _, s := range *f {
|
|
|
|
r += s + ","
|
|
|
|
}
|
|
|
|
return strings.TrimSuffix(r, ",")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *flagOpts) Set(s string) error {
|
|
|
|
*f = append(*f, s)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *flagOpts) StringSlice() []string {
|
|
|
|
var r []string
|
|
|
|
for _, s := range *f {
|
|
|
|
r = append(r, s)
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
saveFile = flag.Bool("t", false,
|
|
|
|
"Use saved file and persist tunnel(If false, tunnel will not persist after program is stopped.")
|
|
|
|
startUp = flag.Bool("s", false,
|
|
|
|
"Start a tunnel with the passed parameters(Otherwise, they will be treated as default values.)")
|
|
|
|
encryptLeaseSet = flag.Bool("l", true,
|
|
|
|
"Use an encrypted leaseset(true or false)")
|
|
|
|
encryptKeyFiles = flag.String("cr", "",
|
|
|
|
"Encrypt/decrypt the key files with a passfile")
|
|
|
|
inAllowZeroHop = flag.Bool("zi", false,
|
|
|
|
"Allow zero-hop, non-anonymous tunnels in(true or false)")
|
|
|
|
outAllowZeroHop = flag.Bool("zo", false,
|
|
|
|
"Allow zero-hop, non-anonymous tunnels out(true or false)")
|
|
|
|
useCompression = flag.Bool("z", false,
|
|
|
|
"Uze gzip(true or false)")
|
|
|
|
reduceIdle = flag.Bool("r", false,
|
|
|
|
"Reduce tunnel quantity when idle(true or false)")
|
|
|
|
closeIdle = flag.Bool("x", false,
|
|
|
|
"Close tunnel group after idle(true or false)")
|
|
|
|
udpMode = flag.Bool("u", false,
|
|
|
|
"UDP mode(true or false)")
|
|
|
|
client = flag.Bool("c", false,
|
|
|
|
"Client proxy mode(true or false)")
|
|
|
|
injectHeaders = flag.Bool("ih", false,
|
|
|
|
"Inject X-I2P-DEST headers")
|
|
|
|
webAdmin = flag.Bool("w", true,
|
|
|
|
"Start web administration interface")
|
|
|
|
sigType = flag.String("st", "",
|
|
|
|
"Signature type")
|
|
|
|
webPort = flag.String("wp", "7957",
|
|
|
|
"Web port")
|
|
|
|
webUser = flag.String("webuser", "samcatd",
|
|
|
|
"Web interface username")
|
|
|
|
webPass = flag.String("webpass", "",
|
|
|
|
"Web interface password")
|
|
|
|
webCSS = flag.String("css", "css/styles.css",
|
|
|
|
"custom CSS for web interface")
|
|
|
|
webJS = flag.String("js", "js/scripts.js",
|
|
|
|
"custom JS for web interface")
|
2019-09-05 01:45:17 -04:00
|
|
|
webDir = flag.String("wwwdir", "./www",
|
|
|
|
"Default www directory to serve if starting eephttpd")
|
2019-05-11 00:43:46 -04:00
|
|
|
leaseSetKey = flag.String("k", "none",
|
|
|
|
"key for encrypted leaseset")
|
|
|
|
leaseSetPrivateKey = flag.String("pk", "none",
|
|
|
|
"private key for encrypted leaseset")
|
|
|
|
leaseSetPrivateSigningKey = flag.String("psk", "none",
|
|
|
|
"private signing key for encrypted leaseset")
|
|
|
|
targetDir = flag.String("d", "",
|
|
|
|
"Directory to save tunnel configuration file in.")
|
|
|
|
targetDest = flag.String("de", "",
|
|
|
|
"Destination to connect client's to by default.")
|
|
|
|
iniFile = flag.String("f", "none",
|
|
|
|
"Use an ini file for configuration(config file options override passed arguments for now.)")
|
|
|
|
/*targetDestination = flag.String("i", "none",
|
|
|
|
"Destination for client tunnels. Ignored for service tunnels.")*/
|
|
|
|
targetHost = flag.String("h", "127.0.0.1",
|
|
|
|
"Target host(Host of service to forward to i2p)")
|
|
|
|
targetPort = flag.String("p", "8081",
|
|
|
|
"Target port(Port of service to forward to i2p)")
|
|
|
|
targetPort443 = flag.String("tls", "",
|
|
|
|
"(Currently inoperative. Target TLS port(HTTPS Port of service to forward to i2p)")
|
2019-08-14 19:05:58 -04:00
|
|
|
peoplehash = flag.String("hashhash", "",
|
|
|
|
"32-word mnemonic representing a .b32.i2p address(will output .b32.i2p address and quit)")
|
2019-05-11 00:43:46 -04:00
|
|
|
samHost = flag.String("sh", "127.0.0.1",
|
|
|
|
"SAM host")
|
|
|
|
samPort = flag.String("sp", "7656",
|
|
|
|
"SAM port")
|
|
|
|
tunName = flag.String("n", "forwarder",
|
|
|
|
"Tunnel name, this must be unique but can be anything.")
|
|
|
|
accessListType = flag.String("a", "none",
|
2020-09-20 16:58:04 -04:00
|
|
|
"Type of access list to use, can be \"allowlist\" \"blocklist\" or \"none\".")
|
2019-05-11 00:43:46 -04:00
|
|
|
inLength = flag.Int("il", 3,
|
|
|
|
"Set inbound tunnel length(0 to 7)")
|
|
|
|
outLength = flag.Int("ol", 3,
|
|
|
|
"Set outbound tunnel length(0 to 7)")
|
|
|
|
inQuantity = flag.Int("iq", 6,
|
|
|
|
"Set inbound tunnel quantity(0 to 15)")
|
|
|
|
outQuantity = flag.Int("oq", 6,
|
|
|
|
"Set outbound tunnel quantity(0 to 15)")
|
|
|
|
inVariance = flag.Int("iv", 0,
|
|
|
|
"Set inbound tunnel length variance(-7 to 7)")
|
|
|
|
outVariance = flag.Int("ov", 0,
|
|
|
|
"Set outbound tunnel length variance(-7 to 7)")
|
|
|
|
inBackupQuantity = flag.Int("ib", 2,
|
|
|
|
"Set inbound tunnel backup quantity(0 to 5)")
|
|
|
|
outBackupQuantity = flag.Int("ob", 2,
|
|
|
|
"Set outbound tunnel backup quantity(0 to 5)")
|
|
|
|
reduceIdleTime = flag.Int("rt", 600000,
|
|
|
|
"Reduce tunnel quantity after X (milliseconds)")
|
|
|
|
closeIdleTime = flag.Int("ct", 600000,
|
|
|
|
"Close tunnel group after X (milliseconds)")
|
|
|
|
reduceIdleQuantity = flag.Int("rq", 3,
|
|
|
|
"Reduce idle tunnel quantity to X (0 to 5)")
|
|
|
|
readKeys = flag.String("conv", "", "Display the base32 and base64 values of a specified .i2pkeys file")
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2019-05-11 15:37:32 -04:00
|
|
|
err error
|
|
|
|
accessList flagOpts
|
|
|
|
config *i2ptunconf.Conf
|
2019-05-11 00:43:46 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
lb := littleboss.New("service-name")
|
|
|
|
lb.Run(func(ctx context.Context) {
|
|
|
|
lbMain(ctx)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func lbMain(ctx context.Context) {
|
|
|
|
flag.Var(&accessList, "accesslist", "Specify an access list member(can be used multiple times)")
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
if *readKeys != "" {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-08-14 19:05:58 -04:00
|
|
|
if *peoplehash != "" {
|
|
|
|
slice := strings.Split(*peoplehash, " ")
|
|
|
|
if length, err := strconv.Atoi(slice[len(slice)-1]); err == nil {
|
|
|
|
Hasher, err := hashhash.NewHasher(length)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2019-08-14 19:19:28 -04:00
|
|
|
lhash, err := Hasher.Unfriendlyslice(slice[0 : len(slice)-2])
|
|
|
|
if err != nil {
|
2019-08-14 19:05:58 -04:00
|
|
|
return
|
|
|
|
}
|
2019-08-14 19:19:28 -04:00
|
|
|
log.Println(lhash + ".b32.i2p")
|
2019-08-14 19:05:58 -04:00
|
|
|
} else {
|
|
|
|
Hasher, err := hashhash.NewHasher(52)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
lhash, err := Hasher.Unfriendlyslice(slice)
|
2019-08-14 19:19:28 -04:00
|
|
|
if err != nil {
|
2019-08-14 19:05:58 -04:00
|
|
|
return
|
|
|
|
}
|
2019-08-14 19:19:28 -04:00
|
|
|
log.Println(lhash + ".b32.i2p")
|
2019-08-14 19:05:58 -04:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-05-11 15:37:32 -04:00
|
|
|
config = &i2ptunconf.Conf{}
|
2019-05-11 00:43:46 -04:00
|
|
|
if *iniFile != "none" && *iniFile != "" {
|
|
|
|
config, err = i2ptunconf.NewI2PTunConf(*iniFile)
|
|
|
|
} else {
|
2019-05-11 15:37:32 -04:00
|
|
|
config = i2ptunconf.NewI2PBlankTunConf()
|
2019-05-11 00:43:46 -04:00
|
|
|
*startUp = true
|
|
|
|
}
|
|
|
|
config.TargetHost = config.GetHost(*targetHost, "127.0.0.1")
|
|
|
|
config.TargetPort = config.GetPort(*targetPort, "8081")
|
2019-08-31 13:22:12 -04:00
|
|
|
config.FilePath = *iniFile
|
2019-05-11 00:43:46 -04:00
|
|
|
config.SaveFile = config.GetSaveFile(*saveFile, true)
|
|
|
|
config.SaveDirectory = config.GetDir(*targetDir, "../")
|
|
|
|
config.SamHost = config.GetSAMHost(*samHost, "127.0.0.1")
|
|
|
|
config.SamPort = config.GetSAMPort(*samPort, "7656")
|
|
|
|
config.TunName = config.GetKeys(*tunName, "forwarder")
|
|
|
|
config.SigType = config.GetSigType(*sigType, "EdDSA_SHA512_Ed25519")
|
|
|
|
config.InLength = config.GetInLength(*inLength, 3)
|
|
|
|
config.OutLength = config.GetOutLength(*outLength, 3)
|
|
|
|
config.InVariance = config.GetInVariance(*inVariance, 0)
|
|
|
|
config.OutVariance = config.GetOutVariance(*outVariance, 0)
|
|
|
|
config.InQuantity = config.GetInQuantity(*inQuantity, 6)
|
|
|
|
config.OutQuantity = config.GetOutQuantity(*outQuantity, 6)
|
|
|
|
config.InBackupQuantity = config.GetInBackups(*inBackupQuantity, 5)
|
|
|
|
config.OutBackupQuantity = config.GetOutBackups(*outBackupQuantity, 5)
|
|
|
|
config.EncryptLeaseSet = config.GetEncryptLeaseset(*encryptLeaseSet, false)
|
|
|
|
config.LeaseSetKey = config.GetLeasesetKey(*leaseSetKey, "")
|
|
|
|
config.LeaseSetPrivateKey = config.GetLeasesetPrivateKey(*leaseSetPrivateKey, "")
|
|
|
|
config.LeaseSetPrivateSigningKey = config.GetLeasesetPrivateSigningKey(*leaseSetPrivateSigningKey, "")
|
|
|
|
config.InAllowZeroHop = config.GetInAllowZeroHop(*inAllowZeroHop, false)
|
|
|
|
config.OutAllowZeroHop = config.GetOutAllowZeroHop(*outAllowZeroHop, false)
|
|
|
|
config.UseCompression = config.GetUseCompression(*useCompression, true)
|
|
|
|
config.ReduceIdle = config.GetReduceOnIdle(*reduceIdle, true)
|
|
|
|
config.ReduceIdleTime = config.GetReduceIdleTime(*reduceIdleTime, 600000)
|
|
|
|
config.ReduceIdleQuantity = config.GetReduceIdleQuantity(*reduceIdleQuantity, 2)
|
|
|
|
config.AccessListType = config.GetAccessListType(*accessListType, "none")
|
|
|
|
config.CloseIdle = config.GetCloseOnIdle(*closeIdle, false)
|
|
|
|
config.CloseIdleTime = config.GetCloseIdleTime(*closeIdleTime, 600000)
|
2019-08-31 00:13:10 -04:00
|
|
|
config.Type = config.GetTypes(*client, *udpMode, *injectHeaders, "server")
|
2019-05-11 00:43:46 -04:00
|
|
|
config.TargetForPort443 = config.GetPort443(*targetPort443, "")
|
|
|
|
config.KeyFilePath = config.GetKeyFile(*encryptKeyFiles, "")
|
|
|
|
config.ClientDest = config.GetClientDest(*targetDest, "", "")
|
|
|
|
config.UserName = config.GetUserName(*webUser, "samcatd")
|
|
|
|
config.Password = config.GetPassword(*webPass, "")
|
2019-09-05 01:45:17 -04:00
|
|
|
config.ServeDirectory = config.GetWWWDir(*webDir, "./www")
|
2019-05-11 00:43:46 -04:00
|
|
|
|
|
|
|
c := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(c, os.Interrupt)
|
|
|
|
|
|
|
|
if manager, err := sammanager.NewSAMManagerFromConf(
|
|
|
|
config,
|
|
|
|
config.TargetHost,
|
|
|
|
config.TargetPort,
|
|
|
|
config.SamHost,
|
|
|
|
config.SamPort,
|
|
|
|
"localhost",
|
|
|
|
*webPort,
|
|
|
|
*webCSS,
|
|
|
|
*webJS,
|
|
|
|
*startUp,
|
|
|
|
*webAdmin,
|
|
|
|
config.UserName,
|
|
|
|
config.Password,
|
|
|
|
); err == nil {
|
|
|
|
go func() {
|
|
|
|
for sig := range c {
|
|
|
|
if sig == os.Interrupt {
|
|
|
|
manager.Cleanup()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
manager.Serve()
|
|
|
|
} else {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
ctx.Done()
|
|
|
|
}
|