2015-06-24 04:39:46 -07:00
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
package main
import (
"crypto/tls"
"flag"
"log"
2015-06-27 17:52:01 -07:00
"net"
2015-06-24 04:39:46 -07:00
"path/filepath"
"time"
2015-07-20 04:25:08 -07:00
"github.com/juju/ratelimit"
2015-06-24 04:39:46 -07:00
"github.com/syncthing/relaysrv/protocol"
2015-06-27 17:52:01 -07:00
syncthingprotocol "github.com/syncthing/protocol"
2015-06-24 04:39:46 -07:00
)
var (
listenProtocol string
listenSession string
debug bool
sessionAddress [ ] byte
sessionPort uint16
networkTimeout time . Duration
pingInterval time . Duration
messageTimeout time . Duration
2015-07-20 04:25:08 -07:00
sessionLimitBps int
globalLimitBps int
sessionLimiter * ratelimit . Bucket
globalLimiter * ratelimit . Bucket
2015-08-20 03:59:44 -07:00
statusAddr string
2015-06-24 04:39:46 -07:00
)
func main ( ) {
var dir , extAddress string
flag . StringVar ( & listenProtocol , "protocol-listen" , ":22067" , "Protocol listen address" )
flag . StringVar ( & listenSession , "session-listen" , ":22068" , "Session listen address" )
flag . StringVar ( & extAddress , "external-address" , "" , "External address to advertise, defaults no IP and session-listen port, causing clients to use the remote IP from the protocol connection" )
flag . StringVar ( & dir , "keys" , "." , "Directory where cert.pem and key.pem is stored" )
flag . DurationVar ( & networkTimeout , "network-timeout" , 2 * time . Minute , "Timeout for network operations" )
flag . DurationVar ( & pingInterval , "ping-interval" , time . Minute , "How often pings are sent" )
flag . DurationVar ( & messageTimeout , "message-timeout" , time . Minute , "Maximum amount of time we wait for relevant messages to arrive" )
2015-07-20 04:25:08 -07:00
flag . IntVar ( & sessionLimitBps , "per-session-rate" , sessionLimitBps , "Per session rate limit, in bytes/s" )
flag . IntVar ( & globalLimitBps , "global-rate" , globalLimitBps , "Global rate limit, in bytes/s" )
flag . BoolVar ( & debug , "debug" , false , "Enable debug output" )
2015-08-20 03:59:44 -07:00
flag . StringVar ( & statusAddr , "status-srv" , ":22070" , "Listen address for status service (blank to disable)" )
2015-07-20 04:25:08 -07:00
flag . Parse ( )
2015-06-24 04:39:46 -07:00
2015-06-27 17:52:01 -07:00
if extAddress == "" {
extAddress = listenSession
}
addr , err := net . ResolveTCPAddr ( "tcp" , extAddress )
if err != nil {
log . Fatal ( err )
}
sessionAddress = addr . IP [ : ]
sessionPort = uint16 ( addr . Port )
2015-06-24 04:39:46 -07:00
certFile , keyFile := filepath . Join ( dir , "cert.pem" ) , filepath . Join ( dir , "key.pem" )
cert , err := tls . LoadX509KeyPair ( certFile , keyFile )
if err != nil {
log . Fatalln ( "Failed to load X509 key pair:" , err )
}
tlsCfg := & tls . Config {
Certificates : [ ] tls . Certificate { cert } ,
NextProtos : [ ] string { protocol . ProtocolName } ,
ClientAuth : tls . RequestClientCert ,
SessionTicketsDisabled : true ,
InsecureSkipVerify : true ,
MinVersion : tls . VersionTLS12 ,
CipherSuites : [ ] uint16 {
tls . TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
tls . TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
tls . TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ,
tls . TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ,
tls . TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ,
tls . TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ,
} ,
}
2015-06-27 17:52:01 -07:00
id := syncthingprotocol . NewDeviceID ( cert . Certificate [ 0 ] )
if debug {
log . Println ( "ID:" , id )
}
2015-06-24 04:39:46 -07:00
2015-07-20 04:25:08 -07:00
if sessionLimitBps > 0 {
sessionLimiter = ratelimit . NewBucketWithRate ( float64 ( sessionLimitBps ) , int64 ( 2 * sessionLimitBps ) )
}
if globalLimitBps > 0 {
globalLimiter = ratelimit . NewBucketWithRate ( float64 ( globalLimitBps ) , int64 ( 2 * globalLimitBps ) )
}
2015-06-24 04:39:46 -07:00
go sessionListener ( listenSession )
2015-08-20 03:59:44 -07:00
if statusAddr != "" {
go statusService ( statusAddr )
}
2015-06-24 04:39:46 -07:00
protocolListener ( listenProtocol , tlsCfg )
}