/ src / server / torControl.js
torControl.js
  1  import fs from 'fs'
  2  import net from 'net'
  3  const PORT = process.env.PORT || 8003
  4  
  5  if (process.env.ONESHOT) {
  6      ogre((err, onion) => {
  7          if (err) return console.log(err);
  8          console.log(onion)
  9      })
 10  }
 11  
 12  function ogre(callback){
 13      var i = -1
 14      let hiddenServicePortSplit, hiddenServiceDirSplit, onion
 15  	try {
 16  		var cookieBuff = fs.readFileSync(process.env.HOME + '/.tor/control_auth_cookie')
 17  		var cookie = Buffer.from(cookieBuff).toString('hex')
 18  	} catch { 
 19  		console.log("Couldn't access", process.env.HOME + '/.tor/control_auth_cookie')
 20  		return callback("ERR: failed to access cookie")	
 21  	}
 22  	let controlClient = net.connect({host: '127.0.0.1', port: 9061}, () => {
 23  	    controlClient.write('AUTHENTICATE ' + cookie + '\r\n');
 24  	});
 25      controlClient.on('data', (x) => {
 26          i ++
 27          if (i ===0){
 28            controlClient.write("GETCONF HiddenServicePort \r\n")
 29          } else if (i === 1) {
 30            hiddenServicePortSplit = splitFromBuffer(x)
 31            hiddenServicePortSplit = hiddenServicePortSplit.filter(x => x !== 'HiddenServicePort')
 32            controlClient.write("GETCONF HiddenServiceDir \r\n")
 33          } else if (i === 2){
 34            hiddenServiceDirSplit = splitFromBuffer(x)
 35            hiddenServiceDirSplit = hiddenServiceDirSplit.filter(x => x !== 'HiddenServiceDir')
 36            onion = checkCurrentPortHasConfigAndReturnOnion(hiddenServicePortSplit, hiddenServiceDirSplit, PORT)
 37            if (!onion){
 38              let newConf = buildNewConfString(hiddenServicePortSplit, hiddenServiceDirSplit, PORT)
 39              controlClient.write("SETCONF " + newConf + " \r\n")
 40            } else {
 41              controlClient.write("QUIT \r\n" )
 42              callback(null, onion)
 43            }
 44          } else if (i === 3){
 45              controlClient.write("SAVECONF \r\n" )
 46          } else if (i === 4){
 47            controlClient.write("GETCONF HiddenServicePort \r\n")
 48          } else if (i === 5) {
 49            hiddenServicePortSplit = splitFromBuffer(x)
 50            controlClient.write("GETCONF HiddenServiceDir \r\n")
 51          } else if (i === 6){
 52            hiddenServiceDirSplit = splitFromBuffer(x)
 53            onion = checkCurrentPortHasConfigAndReturnOnion(hiddenServicePortSplit, hiddenServiceDirSplit, PORT)
 54            if (!onion){
 55                console.log('guess we failed')
 56                callback('sorry')
 57            } else {
 58                controlClient.write("QUIT \r\n" )
 59                callback(null, onion)
 60            }
 61          }
 62      })
 63  
 64  }
 65  
 66  function splitFromBuffer(x){
 67      return Buffer.from(x)
 68          .toString()
 69          .split(/\r?\n/)
 70          .filter(x => x)
 71          .map(x => x.slice(4));
 72  }
 73  
 74  function buildNewConfString(hiddenServicePortSplit, hiddenServiceDirSplit, port){
 75      let targetDir = process.env.HOME + '/.tor/' + crypto.randomUUID() 
 76      try {
 77          fs.mkdirSync(targetDir, '0700')
 78      } catch (err){
 79          console.log(err)
 80      }
 81  
 82      hiddenServicePortSplit = hiddenServicePortSplit.map(noQuotes => {
 83          return noQuotes.slice(0, 18) + "\"" + noQuotes.slice(18) + "\""
 84      })
 85  
 86      let alternate = []
 87      hiddenServiceDirSplit.forEach((x, i) => {
 88          alternate.push(x)
 89          alternate.push(hiddenServicePortSplit[i])
 90      })
 91      let conffy = ''
 92      conffy += alternate.join(' ')
 93      conffy += " HiddenServiceDir=" + targetDir + " "
 94      conffy += " HiddenServicePort=\"80 127.0.0.1:" + port + "\""
 95      return conffy
 96  }
 97  
 98  function checkCurrentPortHasConfigAndReturnOnion(hiddenServicePortSplit, hiddenServiceDirSplit, port=8003){
 99      let onion = false
100  
101      hiddenServicePortSplit.forEach((x, i) => {
102          if (x.indexOf(port) > -1){
103              let directory = hiddenServiceDirSplit[i].slice(17)
104              onion = fs.readFileSync(directory + '/hostname', {encoding:'utf8'})
105          }
106      })
107  
108      return onion
109  }
110  
111  export default ogre