handle_charon.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright 2017 flannel authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build !windows
  15. package ipsec
  16. import (
  17. "fmt"
  18. "net"
  19. "os"
  20. "os/exec"
  21. "strings"
  22. "sync"
  23. "syscall"
  24. "time"
  25. "github.com/bronze1man/goStrongswanVici"
  26. "github.com/coreos/flannel/subnet"
  27. log "github.com/golang/glog"
  28. "golang.org/x/net/context"
  29. )
  30. type Uri struct {
  31. network, address string
  32. }
  33. type CharonIKEDaemon struct {
  34. viciUri Uri
  35. espProposal string
  36. ctx context.Context
  37. }
  38. func NewCharonIKEDaemon(ctx context.Context, wg sync.WaitGroup, espProposal string) (*CharonIKEDaemon, error) {
  39. charon := &CharonIKEDaemon{ctx: ctx, espProposal: espProposal}
  40. addr := strings.Split("unix:///var/run/charon.vici", "://")
  41. charon.viciUri = Uri{addr[0], addr[1]}
  42. cmd, err := charon.runBundled("/usr/lib/strongswan/charon")
  43. if err != nil {
  44. log.Errorf("Error starting charon daemon: %v", err)
  45. return nil, err
  46. } else {
  47. log.Info("Charon daemon started")
  48. }
  49. wg.Add(1)
  50. go func() {
  51. select {
  52. case <-ctx.Done():
  53. cmd.Process.Signal(syscall.SIGTERM)
  54. cmd.Wait()
  55. log.Infof("Stopped charon daemon")
  56. wg.Done()
  57. }
  58. }()
  59. return charon, nil
  60. }
  61. func (charon *CharonIKEDaemon) getClient(wait bool) (client *goStrongswanVici.ClientConn, err error) {
  62. for {
  63. socket_conn, err := net.Dial(charon.viciUri.network, charon.viciUri.address)
  64. if err == nil {
  65. return goStrongswanVici.NewClientConn(socket_conn), nil
  66. } else {
  67. if wait {
  68. select {
  69. case <-charon.ctx.Done():
  70. log.Error("Cancel waiting for charon")
  71. return nil, err
  72. default:
  73. log.Errorf("ClientConnection failed: %v", err)
  74. }
  75. log.Info("Retrying in a second ...")
  76. time.Sleep(time.Second)
  77. } else {
  78. return nil, err
  79. }
  80. }
  81. }
  82. }
  83. func (charon *CharonIKEDaemon) runBundled(execPath string) (cmd *exec.Cmd, err error) {
  84. path, err := exec.LookPath(execPath)
  85. if err != nil {
  86. return nil, err
  87. }
  88. cmd = &exec.Cmd{
  89. Path: path,
  90. SysProcAttr: &syscall.SysProcAttr{
  91. Pdeathsig: syscall.SIGTERM,
  92. },
  93. Stdout: os.Stdout,
  94. Stderr: os.Stderr,
  95. }
  96. err = cmd.Start()
  97. return
  98. }
  99. func (charon *CharonIKEDaemon) LoadSharedKey(remotePublicIP, password string) error {
  100. var err error
  101. var client *goStrongswanVici.ClientConn
  102. client, err = charon.getClient(true)
  103. if err != nil {
  104. log.Errorf("Failed to acquire Vici client: %v", err)
  105. return err
  106. }
  107. defer client.Close()
  108. sharedKey := &goStrongswanVici.Key{
  109. Typ: "IKE",
  110. Data: password,
  111. Owners: []string{remotePublicIP},
  112. }
  113. for {
  114. err = client.LoadShared(sharedKey)
  115. if err != nil {
  116. log.Errorf("Failed to load my key. Retrying. %v", err)
  117. time.Sleep(time.Second)
  118. } else {
  119. break
  120. }
  121. }
  122. log.Infof("Loaded shared key for: %v", remotePublicIP)
  123. return nil
  124. }
  125. func (charon *CharonIKEDaemon) LoadConnection(localLease, remoteLease *subnet.Lease,
  126. reqID, encap string) error {
  127. var err error
  128. var client *goStrongswanVici.ClientConn
  129. client, err = charon.getClient(true)
  130. if err != nil {
  131. log.Errorf("Failed to acquire Vici client: %s", err)
  132. return err
  133. }
  134. defer client.Close()
  135. childConfMap := make(map[string]goStrongswanVici.ChildSAConf)
  136. childSAConf := goStrongswanVici.ChildSAConf{
  137. Local_ts: []string{localLease.Subnet.String()},
  138. Remote_ts: []string{remoteLease.Subnet.String()},
  139. ESPProposals: []string{charon.espProposal},
  140. StartAction: "start",
  141. CloseAction: "trap",
  142. Mode: "tunnel",
  143. ReqID: reqID,
  144. // RekeyTime: rekeyTime,
  145. InstallPolicy: "no",
  146. }
  147. childSAConfName := formatChildSAConfName(localLease, remoteLease)
  148. childConfMap[childSAConfName] = childSAConf
  149. localAuthConf := goStrongswanVici.AuthConf{
  150. AuthMethod: "psk",
  151. }
  152. remoteAuthConf := goStrongswanVici.AuthConf{
  153. AuthMethod: "psk",
  154. }
  155. ikeConf := goStrongswanVici.IKEConf{
  156. LocalAddrs: []string{localLease.Attrs.PublicIP.String()},
  157. RemoteAddrs: []string{remoteLease.Attrs.PublicIP.String()},
  158. Proposals: []string{"aes256-sha256-modp4096"},
  159. Version: "2",
  160. KeyingTries: "0", //continues to retry
  161. LocalAuth: localAuthConf,
  162. RemoteAuth: remoteAuthConf,
  163. Children: childConfMap,
  164. Encap: encap,
  165. }
  166. ikeConfMap := make(map[string]goStrongswanVici.IKEConf)
  167. connectionName := formatConnectionName(localLease, remoteLease)
  168. ikeConfMap[connectionName] = ikeConf
  169. err = client.LoadConn(&ikeConfMap)
  170. if err != nil {
  171. return err
  172. }
  173. log.Infof("Loaded connection: %v", connectionName)
  174. return nil
  175. }
  176. func (charon *CharonIKEDaemon) UnloadCharonConnection(localLease,
  177. remoteLease *subnet.Lease) error {
  178. client, err := charon.getClient(false)
  179. if err != nil {
  180. log.Errorf("Failed to acquire Vici client: %s", err)
  181. return err
  182. }
  183. defer client.Close()
  184. connectionName := formatConnectionName(localLease, remoteLease)
  185. unloadConnRequest := &goStrongswanVici.UnloadConnRequest{
  186. Name: connectionName,
  187. }
  188. err = client.UnloadConn(unloadConnRequest)
  189. if err != nil {
  190. return err
  191. }
  192. log.Infof("Unloaded connection: %v", connectionName)
  193. return nil
  194. }
  195. func formatConnectionName(localLease, remoteLease *subnet.Lease) string {
  196. return fmt.Sprintf("%s-%s-%s-%s", localLease.Attrs.PublicIP,
  197. localLease.Subnet, remoteLease.Subnet, remoteLease.Attrs.PublicIP)
  198. }
  199. func formatChildSAConfName(localLease, remoteLease *subnet.Lease) string {
  200. return fmt.Sprintf("%s-%s", localLease.Subnet, remoteLease.Subnet)
  201. }