assets.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. package tapdance
  2. import (
  3. "crypto/x509"
  4. "encoding/binary"
  5. "encoding/hex"
  6. "errors"
  7. "io/ioutil"
  8. "net"
  9. "os"
  10. "path"
  11. "strings"
  12. "sync"
  13. "github.com/golang/protobuf/proto"
  14. pb "github.com/refraction-networking/gotapdance/protobuf"
  15. ps "github.com/refraction-networking/gotapdance/tapdance/phantoms"
  16. )
  17. type assets struct {
  18. sync.RWMutex
  19. path string
  20. config *pb.ClientConf
  21. roots *x509.CertPool
  22. filenameRoots string
  23. filenameClientConf string
  24. socksAddr string
  25. }
  26. // could reset this internally to refresh assets and avoid woes of singleton testing
  27. var assetsInstance *assets
  28. var assetsOnce sync.Once
  29. // Assets is an access point to asset managing singleton.
  30. // First access to singleton sets path. Assets(), if called
  31. // before SetAssetsDir() sets path to "./assets/"
  32. func Assets() *assets {
  33. var err error
  34. _initAssets := func() { err = initAssets("./assets/") }
  35. assetsOnce.Do(_initAssets)
  36. if err != nil {
  37. Logger().Warnf("error getting assets: %v", err)
  38. }
  39. return assetsInstance
  40. }
  41. // AssetsSetDir sets the directory to read assets from.
  42. // Functionally equivalent to Assets() after initialization, unless dir changes.
  43. func AssetsSetDir(dir string) (*assets, error) {
  44. var err error
  45. _initAssets := func() { err = initAssets(dir) }
  46. if assetsInstance != nil {
  47. assetsInstance.Lock()
  48. defer assetsInstance.Unlock()
  49. if dir != assetsInstance.path {
  50. if _, err := os.Stat(dir); err != nil {
  51. Logger().Warnf("Assets path unchanged %v.\n", err)
  52. return assetsInstance, err
  53. }
  54. Logger().Warnf("Assets path changed %s->%s. (Re)initializing", assetsInstance.path, dir)
  55. assetsInstance.path = dir
  56. err = assetsInstance.readConfigs()
  57. return assetsInstance, err
  58. }
  59. }
  60. assetsOnce.Do(_initAssets)
  61. return assetsInstance, err
  62. }
  63. func getDefaultKey() []byte {
  64. keyStr := "a1cb97be697c5ed5aefd78ffa4db7e68101024603511e40a89951bc158807177"
  65. key := make([]byte, hex.DecodedLen(len(keyStr)))
  66. hex.Decode(key, []byte(keyStr))
  67. return key
  68. }
  69. func getDefaultTapdanceKey() []byte {
  70. keyStr := "515868be7f45ab6f310afed4b229b7a479fc9fde553dea4ccdb369ab1899e70c"
  71. key := make([]byte, hex.DecodedLen(len(keyStr)))
  72. hex.Decode(key, []byte(keyStr))
  73. return key
  74. }
  75. func initAssets(path string) error {
  76. var defaultDecoys = []*pb.TLSDecoySpec{
  77. pb.InitTLSDecoySpec("192.122.190.104", "tapdance1.freeaeskey.xyz"),
  78. pb.InitTLSDecoySpec("192.122.190.105", "tapdance2.freeaeskey.xyz"),
  79. pb.InitTLSDecoySpec("192.122.190.106", "tapdance3.freeaeskey.xyz"),
  80. }
  81. defaultKey := getDefaultTapdanceKey()
  82. defaultConjureKey := getDefaultKey()
  83. defualtKeyType := pb.KeyType_AES_GCM_128
  84. defaultPubKey := pb.PubKey{Key: defaultKey, Type: &defualtKeyType}
  85. defaultConjurePubKey := pb.PubKey{Key: defaultConjureKey, Type: &defualtKeyType}
  86. defaultGeneration := uint32(1)
  87. defaultDecoyList := pb.DecoyList{TlsDecoys: defaultDecoys}
  88. defaultClientConf := pb.ClientConf{
  89. DecoyList: &defaultDecoyList,
  90. DefaultPubkey: &defaultPubKey,
  91. ConjurePubkey: &defaultConjurePubKey,
  92. Generation: &defaultGeneration,
  93. }
  94. assetsInstance = &assets{
  95. path: path,
  96. config: &defaultClientConf,
  97. filenameRoots: "roots",
  98. filenameClientConf: "ClientConf",
  99. socksAddr: "",
  100. }
  101. err := assetsInstance.readConfigs()
  102. return err
  103. }
  104. func (a *assets) GetAssetsDir() string {
  105. a.RLock()
  106. defer a.RUnlock()
  107. return a.path
  108. }
  109. func (a *assets) readConfigs() error {
  110. readRoots := func(filename string) error {
  111. rootCerts, err := ioutil.ReadFile(filename)
  112. if err != nil {
  113. return err
  114. }
  115. roots := x509.NewCertPool()
  116. ok := roots.AppendCertsFromPEM(rootCerts)
  117. if !ok {
  118. return errors.New("Failed to parse root certificates")
  119. }
  120. a.roots = roots
  121. return nil
  122. }
  123. readClientConf := func(filename string) error {
  124. buf, err := ioutil.ReadFile(filename)
  125. if err != nil {
  126. return err
  127. }
  128. clientConf := &pb.ClientConf{}
  129. err = proto.Unmarshal(buf, clientConf)
  130. if err != nil {
  131. return err
  132. }
  133. a.config = clientConf
  134. return nil
  135. }
  136. var err error
  137. Logger().Infoln("Assets: reading from folder " + a.path)
  138. rootsFilename := path.Join(a.path, a.filenameRoots)
  139. err = readRoots(rootsFilename)
  140. if err != nil {
  141. Logger().Warn("Assets: failed to read root ca file: " + err.Error())
  142. } else {
  143. Logger().Infoln("X.509 root CAs successfully read from " + rootsFilename)
  144. }
  145. // Parse ClientConf for Decoys and Phantoms List
  146. clientConfFilename := path.Join(a.path, a.filenameClientConf)
  147. err = readClientConf(clientConfFilename)
  148. if err != nil {
  149. Logger().Warn("Assets: failed to read ClientConf file: " + err.Error())
  150. } else {
  151. Logger().Infoln("Client config successfully read from " + clientConfFilename)
  152. }
  153. return err
  154. }
  155. // Picks random decoy, returns Server Name Indication and addr in format ipv4:port
  156. func (a *assets) GetDecoyAddress() (sni string, addr string) {
  157. a.RLock()
  158. defer a.RUnlock()
  159. decoys := a.config.GetDecoyList().GetTlsDecoys()
  160. if len(decoys) == 0 {
  161. return "", ""
  162. }
  163. decoyIndex := getRandInt(0, len(decoys)-1)
  164. ip := make(net.IP, 4)
  165. binary.BigEndian.PutUint32(ip, decoys[decoyIndex].GetIpv4Addr())
  166. //[TODO]{priority:winter-break}: what checks need to be done, and what's guaranteed?
  167. addr = ip.To4().String() + ":443"
  168. sni = decoys[decoyIndex].GetHostname()
  169. return
  170. }
  171. // Get all Decoys from ClientConf
  172. func (a *assets) GetAllDecoys() []*pb.TLSDecoySpec {
  173. return a.config.GetDecoyList().GetTlsDecoys()
  174. }
  175. // Get all Decoys from ClientConf that have an IPv6 address
  176. func (a *assets) GetV6Decoys() []*pb.TLSDecoySpec {
  177. v6Decoys := make([]*pb.TLSDecoySpec, 0)
  178. allDecoys := a.config.GetDecoyList().GetTlsDecoys()
  179. for _, decoy := range allDecoys {
  180. if decoy.GetIpv6Addr() != nil {
  181. v6Decoys = append(v6Decoys, decoy)
  182. }
  183. }
  184. return v6Decoys
  185. }
  186. // Get all Decoys from ClientConf that have an IPv6 address
  187. func (a *assets) GetV4Decoys() []*pb.TLSDecoySpec {
  188. v6Decoys := make([]*pb.TLSDecoySpec, 0)
  189. allDecoys := a.config.GetDecoyList().GetTlsDecoys()
  190. for _, decoy := range allDecoys {
  191. if decoy.GetIpv4Addr() != 0 {
  192. v6Decoys = append(v6Decoys, decoy)
  193. }
  194. }
  195. return v6Decoys
  196. }
  197. // GetDecoy - Gets random DecoySpec
  198. func (a *assets) GetDecoy() *pb.TLSDecoySpec {
  199. a.RLock()
  200. defer a.RUnlock()
  201. decoys := a.config.GetDecoyList().GetTlsDecoys()
  202. chosenDecoy := &pb.TLSDecoySpec{}
  203. if len(decoys) == 0 {
  204. return chosenDecoy
  205. }
  206. decoyIndex := getRandInt(0, len(decoys)-1)
  207. chosenDecoy = decoys[decoyIndex]
  208. //[TODO]{priority:soon} stop enforcing values >= defaults.
  209. // Fix ackhole instead
  210. // No value checks when using
  211. if chosenDecoy.GetTimeout() < timeoutMin {
  212. timeout := uint32(timeoutMax)
  213. chosenDecoy.Timeout = &timeout
  214. }
  215. if chosenDecoy.GetTcpwin() < sendLimitMin {
  216. tcpWin := uint32(sendLimitMax)
  217. chosenDecoy.Tcpwin = &tcpWin
  218. }
  219. return chosenDecoy
  220. }
  221. // GetDecoy - Gets random IPv6 DecoySpec
  222. func (a *assets) GetV6Decoy() *pb.TLSDecoySpec {
  223. a.RLock()
  224. defer a.RUnlock()
  225. decoys := a.GetV6Decoys()
  226. chosenDecoy := &pb.TLSDecoySpec{}
  227. if len(decoys) == 0 {
  228. return chosenDecoy
  229. }
  230. decoyIndex := getRandInt(0, len(decoys)-1)
  231. chosenDecoy = decoys[decoyIndex]
  232. // No enforcing TCPWIN etc. values because this is conjure only
  233. return chosenDecoy
  234. }
  235. func (a *assets) GetRoots() *x509.CertPool {
  236. a.RLock()
  237. defer a.RUnlock()
  238. return a.roots
  239. }
  240. func (a *assets) GetPubkey() *[32]byte {
  241. a.RLock()
  242. defer a.RUnlock()
  243. var pKey [32]byte
  244. copy(pKey[:], a.config.GetDefaultPubkey().GetKey()[:])
  245. return &pKey
  246. }
  247. func (a *assets) GetConjurePubkey() *[32]byte {
  248. a.RLock()
  249. defer a.RUnlock()
  250. var pKey [32]byte
  251. copy(pKey[:], a.config.GetConjurePubkey().GetKey()[:])
  252. return &pKey
  253. }
  254. func (a *assets) GetGeneration() uint32 {
  255. a.RLock()
  256. defer a.RUnlock()
  257. return a.config.GetGeneration()
  258. }
  259. // Set ClientConf generation and store config to disk
  260. func (a *assets) SetGeneration(gen uint32) (err error) {
  261. a.Lock()
  262. defer a.Unlock()
  263. copyGen := gen
  264. a.config.Generation = &copyGen
  265. err = a.saveClientConf()
  266. return
  267. }
  268. // Set Public key and store config to disk
  269. func (a *assets) SetPubkey(pubkey *pb.PubKey) (err error) {
  270. a.Lock()
  271. defer a.Unlock()
  272. a.config.DefaultPubkey = pubkey
  273. err = a.saveClientConf()
  274. return
  275. }
  276. // Set ClientConf and store config to disk - if an error occurs (parse error or
  277. // write to file error) the error will be logged and the update will be aborted.
  278. func (a *assets) SetClientConf(conf *pb.ClientConf) (err error) {
  279. a.Lock()
  280. defer a.Unlock()
  281. origConf := a.config
  282. a.config = conf
  283. err = a.saveClientConf()
  284. if err != nil {
  285. a.config = origConf
  286. }
  287. return
  288. }
  289. // Not goroutine-safe, use at your own risk
  290. func (a *assets) GetClientConfPtr() *pb.ClientConf {
  291. return a.config
  292. }
  293. // Overwrite currently used decoys and store config to disk
  294. func (a *assets) SetDecoys(decoys []*pb.TLSDecoySpec) (err error) {
  295. a.Lock()
  296. defer a.Unlock()
  297. if a.config.DecoyList == nil {
  298. a.config.DecoyList = &pb.DecoyList{}
  299. }
  300. a.config.DecoyList.TlsDecoys = decoys
  301. err = a.saveClientConf()
  302. return
  303. }
  304. // Checks if decoy is in currently used ClientConf decoys list
  305. func (a *assets) IsDecoyInList(decoy *pb.TLSDecoySpec) bool {
  306. ipv4str := decoy.GetIpAddrStr()
  307. hostname := decoy.GetHostname()
  308. a.RLock()
  309. defer a.RUnlock()
  310. for _, d := range a.config.GetDecoyList().GetTlsDecoys() {
  311. if strings.Compare(d.GetHostname(), hostname) == 0 &&
  312. strings.Compare(d.GetIpAddrStr(), ipv4str) == 0 {
  313. return true
  314. }
  315. }
  316. return false
  317. }
  318. func (a *assets) saveClientConf() error {
  319. buf, err := proto.Marshal(a.config)
  320. if err != nil {
  321. return err
  322. }
  323. filename := path.Join(a.path, a.filenameClientConf)
  324. tmpFilename := path.Join(a.path, "."+a.filenameClientConf+"."+getRandString(5)+".tmp")
  325. err = ioutil.WriteFile(tmpFilename, buf[:], 0644)
  326. if err != nil {
  327. return err
  328. }
  329. return os.Rename(tmpFilename, filename)
  330. }
  331. // SetStatsSocksAddr - Provide a socks address for reporting stats from the client in the form "addr:port"
  332. func (a *assets) SetStatsSocksAddr(addr string) {
  333. a.socksAddr = addr
  334. }
  335. // GetPhantomSubnets -
  336. func (a *assets) GetPhantomSubnets() *pb.PhantomSubnetsList {
  337. a.RLock()
  338. defer a.RUnlock()
  339. if a.config == nil {
  340. return ps.GetDefaultPhantomSubnets()
  341. }
  342. if phantomSubnetsList := a.config.GetPhantomSubnetsList(); phantomSubnetsList != nil {
  343. return phantomSubnetsList
  344. }
  345. return ps.GetDefaultPhantomSubnets()
  346. }
  347. // SetPhantomSubnets -
  348. func (a *assets) SetPhantomSubnets(subnetConf *pb.PhantomSubnetsList) error {
  349. a.Lock()
  350. defer a.Unlock()
  351. if a.config == nil {
  352. a.config = &pb.ClientConf{}
  353. }
  354. a.config.PhantomSubnetsList = subnetConf
  355. err := a.saveClientConf()
  356. return err
  357. }