ipsec.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. "encoding/json"
  18. "fmt"
  19. "sync"
  20. "golang.org/x/net/context"
  21. "github.com/flannel-io/flannel/backend"
  22. "github.com/flannel-io/flannel/pkg/ip"
  23. "github.com/flannel-io/flannel/subnet"
  24. log "k8s.io/klog"
  25. )
  26. /*
  27. Flannel's approach to IPSec uses Strongswan to handle the key exchange (using IKEv2) and the kernel to handle the
  28. actual encryption.
  29. Flannel runs Strongswan's "charon" as a child process when the ipsec backend is selected and communicates with it
  30. using the "VICI" interface. Strongswan ships a utility "swanctl" which also uses the VICI interface. This utility
  31. is bundled in the flannel container and can help with debugging.
  32. The file "handle_charon.go" contains the logic for working with the charon. It supports creating a "CharonIKEDaemon"
  33. which supports loading the PSK into the charon and adding and removing connections.
  34. The file "handle_xfrm.go" contains functions for adding and removing the ipsec polcies.
  35. ipsec_network.go ties it all together, loading the PSK for current host on startu and as new hosts are added and
  36. removed it, adds/removes the PSK and connection details to strongswan and adds/remove the policy to the kernel.
  37. */
  38. const (
  39. defaultESPProposal = "aes128gcm16-sha256-prfsha256-ecp256"
  40. minPasswordLength = 96
  41. )
  42. func init() {
  43. backend.Register("ipsec", New)
  44. }
  45. type IPSECBackend struct {
  46. sm subnet.Manager
  47. extIface *backend.ExternalInterface
  48. }
  49. func New(sm subnet.Manager, extIface *backend.ExternalInterface) (
  50. backend.Backend, error) {
  51. be := &IPSECBackend{
  52. sm: sm,
  53. extIface: extIface,
  54. }
  55. return be, nil
  56. }
  57. func (be *IPSECBackend) RegisterNetwork(
  58. ctx context.Context, wg *sync.WaitGroup, config *subnet.Config) (backend.Network, error) {
  59. cfg := struct {
  60. UDPEncap bool
  61. ESPProposal string
  62. PSK string
  63. }{
  64. UDPEncap: false,
  65. ESPProposal: defaultESPProposal,
  66. }
  67. if len(config.Backend) > 0 {
  68. if err := json.Unmarshal(config.Backend, &cfg); err != nil {
  69. return nil, fmt.Errorf("error decoding IPSEC backend config: %v", err)
  70. }
  71. }
  72. if len(cfg.PSK) < minPasswordLength {
  73. return nil, fmt.Errorf(
  74. "config error, password should be at least %d characters long",
  75. minPasswordLength)
  76. }
  77. log.Infof("IPSec config: UDPEncap=%v ESPProposal=%s", cfg.UDPEncap, cfg.ESPProposal)
  78. attrs := subnet.LeaseAttrs{
  79. PublicIP: ip.FromIP(be.extIface.ExtAddr),
  80. BackendType: "ipsec",
  81. }
  82. l, err := be.sm.AcquireLease(ctx, &attrs)
  83. switch err {
  84. case nil:
  85. case context.Canceled, context.DeadlineExceeded:
  86. return nil, err
  87. default:
  88. return nil, fmt.Errorf("failed to acquire lease: %v", err)
  89. }
  90. ikeDaemon, err := NewCharonIKEDaemon(ctx, wg, cfg.ESPProposal)
  91. if err != nil {
  92. return nil, fmt.Errorf("error creating CharonIKEDaemon struct: %v", err)
  93. }
  94. return newNetwork(be.sm, be.extIface, cfg.UDPEncap, cfg.PSK, ikeDaemon, l)
  95. }