listener.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package brontide
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "net"
  7. "time"
  8. "github.com/lightningnetwork/lnd/keychain"
  9. )
  10. // defaultHandshakes is the maximum number of handshakes that can be done in
  11. // parallel.
  12. const defaultHandshakes = 1000
  13. // Listener is an implementation of a net.Conn which executes an authenticated
  14. // key exchange and message encryption protocol dubbed "Machine" after
  15. // initial connection acceptance. See the Machine struct for additional
  16. // details w.r.t the handshake and encryption scheme used within the
  17. // connection.
  18. type Listener struct {
  19. localStatic keychain.SingleKeyECDH
  20. tcp *net.TCPListener
  21. handshakeSema chan struct{}
  22. conns chan maybeConn
  23. quit chan struct{}
  24. }
  25. // A compile-time assertion to ensure that Conn meets the net.Listener interface.
  26. var _ net.Listener = (*Listener)(nil)
  27. // NewListener returns a new net.Listener which enforces the Brontide scheme
  28. // during both initial connection establishment and data transfer.
  29. func NewListener(localStatic keychain.SingleKeyECDH,
  30. listenAddr string) (*Listener, error) {
  31. addr, err := net.ResolveTCPAddr("tcp", listenAddr)
  32. if err != nil {
  33. return nil, err
  34. }
  35. l, err := net.ListenTCP("tcp", addr)
  36. if err != nil {
  37. return nil, err
  38. }
  39. brontideListener := &Listener{
  40. localStatic: localStatic,
  41. tcp: l,
  42. handshakeSema: make(chan struct{}, defaultHandshakes),
  43. conns: make(chan maybeConn),
  44. quit: make(chan struct{}),
  45. }
  46. for i := 0; i < defaultHandshakes; i++ {
  47. brontideListener.handshakeSema <- struct{}{}
  48. }
  49. go brontideListener.listen()
  50. return brontideListener, nil
  51. }
  52. // listen accepts connection from the underlying tcp conn, then performs
  53. // the brontinde handshake procedure asynchronously. A maximum of
  54. // defaultHandshakes will be active at any given time.
  55. //
  56. // NOTE: This method must be run as a goroutine.
  57. func (l *Listener) listen() {
  58. for {
  59. select {
  60. case <-l.handshakeSema:
  61. case <-l.quit:
  62. return
  63. }
  64. conn, err := l.tcp.Accept()
  65. if err != nil {
  66. l.rejectConn(err)
  67. l.handshakeSema <- struct{}{}
  68. continue
  69. }
  70. go l.doHandshake(conn)
  71. }
  72. }
  73. // rejectedConnErr is a helper function that prepends the remote address of the
  74. // failed connection attempt to the original error message.
  75. func rejectedConnErr(err error, remoteAddr string) error {
  76. return fmt.Errorf("unable to accept connection from %v: %w", remoteAddr,
  77. err)
  78. }
  79. // doHandshake asynchronously performs the brontide handshake, so that it does
  80. // not block the main accept loop. This prevents peers that delay writing to the
  81. // connection from block other connection attempts.
  82. func (l *Listener) doHandshake(conn net.Conn) {
  83. defer func() { l.handshakeSema <- struct{}{} }()
  84. select {
  85. case <-l.quit:
  86. return
  87. default:
  88. }
  89. remoteAddr := conn.RemoteAddr().String()
  90. brontideConn := &Conn{
  91. conn: conn,
  92. noise: NewBrontideMachine(false, l.localStatic, nil),
  93. }
  94. // We'll ensure that we get ActOne from the remote peer in a timely
  95. // manner. If they don't respond within handshakeReadTimeout, then
  96. // we'll kill the connection.
  97. err := conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
  98. if err != nil {
  99. brontideConn.conn.Close()
  100. l.rejectConn(rejectedConnErr(err, remoteAddr))
  101. return
  102. }
  103. // Attempt to carry out the first act of the handshake protocol. If the
  104. // connecting node doesn't know our long-term static public key, then
  105. // this portion will fail with a non-nil error.
  106. var actOne [ActOneSize]byte
  107. if _, err := io.ReadFull(conn, actOne[:]); err != nil {
  108. brontideConn.conn.Close()
  109. l.rejectConn(rejectedConnErr(err, remoteAddr))
  110. return
  111. }
  112. if err := brontideConn.noise.RecvActOne(actOne); err != nil {
  113. brontideConn.conn.Close()
  114. l.rejectConn(rejectedConnErr(err, remoteAddr))
  115. return
  116. }
  117. // Next, progress the handshake processes by sending over our ephemeral
  118. // key for the session along with an authenticating tag.
  119. actTwo, err := brontideConn.noise.GenActTwo()
  120. if err != nil {
  121. brontideConn.conn.Close()
  122. l.rejectConn(rejectedConnErr(err, remoteAddr))
  123. return
  124. }
  125. if _, err := conn.Write(actTwo[:]); err != nil {
  126. brontideConn.conn.Close()
  127. l.rejectConn(rejectedConnErr(err, remoteAddr))
  128. return
  129. }
  130. select {
  131. case <-l.quit:
  132. return
  133. default:
  134. }
  135. // We'll ensure that we get ActTwo from the remote peer in a timely
  136. // manner. If they don't respond within handshakeReadTimeout, then
  137. // we'll kill the connection.
  138. err = conn.SetReadDeadline(time.Now().Add(handshakeReadTimeout))
  139. if err != nil {
  140. brontideConn.conn.Close()
  141. l.rejectConn(rejectedConnErr(err, remoteAddr))
  142. return
  143. }
  144. // Finally, finish the handshake processes by reading and decrypting
  145. // the connection peer's static public key. If this succeeds then both
  146. // sides have mutually authenticated each other.
  147. var actThree [ActThreeSize]byte
  148. if _, err := io.ReadFull(conn, actThree[:]); err != nil {
  149. brontideConn.conn.Close()
  150. l.rejectConn(rejectedConnErr(err, remoteAddr))
  151. return
  152. }
  153. if err := brontideConn.noise.RecvActThree(actThree); err != nil {
  154. brontideConn.conn.Close()
  155. l.rejectConn(rejectedConnErr(err, remoteAddr))
  156. return
  157. }
  158. // We'll reset the deadline as it's no longer critical beyond the
  159. // initial handshake.
  160. err = conn.SetReadDeadline(time.Time{})
  161. if err != nil {
  162. brontideConn.conn.Close()
  163. l.rejectConn(rejectedConnErr(err, remoteAddr))
  164. return
  165. }
  166. l.acceptConn(brontideConn)
  167. }
  168. // maybeConn holds either a brontide connection or an error returned from the
  169. // handshake.
  170. type maybeConn struct {
  171. conn *Conn
  172. err error
  173. }
  174. // acceptConn returns a connection that successfully performed a handshake.
  175. func (l *Listener) acceptConn(conn *Conn) {
  176. select {
  177. case l.conns <- maybeConn{conn: conn}:
  178. case <-l.quit:
  179. }
  180. }
  181. // rejectConn returns any errors encountered during connection or handshake.
  182. func (l *Listener) rejectConn(err error) {
  183. select {
  184. case l.conns <- maybeConn{err: err}:
  185. case <-l.quit:
  186. }
  187. }
  188. // Accept waits for and returns the next connection to the listener. All
  189. // incoming connections are authenticated via the three act Brontide
  190. // key-exchange scheme. This function will fail with a non-nil error in the
  191. // case that either the handshake breaks down, or the remote peer doesn't know
  192. // our static public key.
  193. //
  194. // Part of the net.Listener interface.
  195. func (l *Listener) Accept() (net.Conn, error) {
  196. select {
  197. case result := <-l.conns:
  198. return result.conn, result.err
  199. case <-l.quit:
  200. return nil, errors.New("brontide connection closed")
  201. }
  202. }
  203. // Close closes the listener. Any blocked Accept operations will be unblocked
  204. // and return errors.
  205. //
  206. // Part of the net.Listener interface.
  207. func (l *Listener) Close() error {
  208. select {
  209. case <-l.quit:
  210. default:
  211. close(l.quit)
  212. }
  213. return l.tcp.Close()
  214. }
  215. // Addr returns the listener's network address.
  216. //
  217. // Part of the net.Listener interface.
  218. func (l *Listener) Addr() net.Addr {
  219. return l.tcp.Addr()
  220. }