Puppet Class: profile::lvs::realserver::ipip

Defined in:
modules/profile/manifests/lvs/realserver/ipip.pp

Overview

SPDX-License-Identifier: Apache-2.0

Class profile::lvs::realserver::ipip.

Sets up the LVS realserver dependencies to handle IPIP encapsulated ingress traffic

Parameters

pools

Pools in the format: {$lvs_name => { services => [$svc1,$svc2,…] } where the services listed are the ones that are needed to serve the lvs pool. So for example if you need both apache and php7 to serve a request from a pool, both should be included.

enabled

Whether to use IPIP encapsulation or not. Allows fine control per host. defaults to false.

ipv4_mss

TCP MSS value for IPv4 traffic. Defaults to 1400 bytes

ipv6_mss

TCP MSS value for IPv6 traffic. Defaults to 1400 bytes

interfaces

Network interfaces handling egress traffic on the realserver. Defaults to the primary interface

Parameters:

  • pools (Hash) (defaults to: lookup('profile::lvs::realserver::pools', {'default_value' => {}}))
  • enabled (Boolean) (defaults to: lookup('profile::lvs::realserver::ipip::enabled', {'default_value' => false}))
  • ipv4_mss (Integer[536, 1480]) (defaults to: lookup('profile::lvs::realserver::ipip::ipv4_mss', {'default_value' => 1400}))
  • ipv6_mss (Integer[1220, 1440]) (defaults to: lookup('profile::lvs::realserver::ipip::ipv6_mss', {'default_value' => 1400}))
  • interfaces (Array[String, 1]) (defaults to: lookup('profile::lvs::realserver::ipip::interfaces'))
  • firewall_provider (Firewall::Provider) (defaults to: lookup('profile::firewall::provider'))


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'modules/profile/manifests/lvs/realserver/ipip.pp', line 20

class profile::lvs::realserver::ipip(
    Hash $pools = lookup('profile::lvs::realserver::pools', {'default_value'                                                 => {}}),
    Boolean $enabled = lookup('profile::lvs::realserver::ipip::enabled', {'default_value'                                    => false}),
    Integer[536, 1480] $ipv4_mss = lookup('profile::lvs::realserver::ipip::ipv4_mss', {'default_value'                       => 1400}),
    Integer[1220, 1440] $ipv6_mss = lookup('profile::lvs::realserver::ipip::ipv6_mss', {'default_value'                      => 1400}),
    Array[String, 1] $interfaces = lookup('profile::lvs::realserver::ipip::interfaces'),
    Firewall::Provider $firewall_provider = lookup('profile::firewall::provider'),
) {
    $present_pools = $pools.keys()
    $services = wmflib::service::fetch(true).filter |$lvs_name, $svc| {$lvs_name in $present_pools}
    $clamped_ipport = wmflib::service::get_ipport_for_ipip_services($services, $::site)

    $ensure = stdlib::ensure($enabled)
    $ensure_clamper = stdlib::ensure($enabled and $firewall_provider == 'none')
    $ensure_ferm_mss = stdlib::ensure($enabled and $firewall_provider == 'ferm')
    if $enabled and $ensure_clamper == 'absent' and $ensure_ferm_mss == 'absent' {
        fail('unsupported realserver setup')
    }

    # Provide ingress interfaces for both IPv4 and IPv6 traffic
    interface::ipip { 'ipip_ipv4':
        ensure    => $ensure,
        interface => 'ipip0',
        family    => 'inet',
        address   => '127.0.0.42',
    }
    interface::ipip { 'ipip_ipv6':
        ensure    => $ensure,
        interface => 'ipip60',
        family    => 'inet6',
    }

    $interfaces.each |String $interface| {
        interface::clsact { "clsact_${interface}":
            ensure    => $ensure_clamper,
            interface => $interface,
        }
    }

    if $enabled {
        $disable_rp_filter_ifaces = ['ipip0', 'ipip60', $facts['interface_primary']]
        $disable_rp_filter_ifaces.each |String $interface| {
            $require_interface = $interface? {
                'ipip0'  => Interface::Ipip['ipip_ipv4'],
                'ipip60' => Interface::Ipip['ipip_ipv6'],
                default  => undef,
            }
            exec { "disable-rp-filter-${interface}":
                command => "/usr/sbin/sysctl -q net.ipv4.conf.${interface}.rp_filter=0",
                unless  => "/usr/sbin/sysctl -n net.ipv4.conf.${interface}.rp_filter |grep -- '0'",
                require => $require_interface,
            }
        }
    }

    # We need TCP MSS clamping here
    package { 'tcp-mss-clamper':
        ensure => $ensure_clamper,
    }

    $prometheus_addr = ':2200'
    systemd::service { 'tcp-mss-clamper':
        ensure               => $ensure_clamper,
        content              => systemd_template('tcp-mss-clamper'),
        monitoring_enabled   => true,
        monitoring_notes_url => 'https://wikitech.wikimedia.org/wiki/LVS#IPIP_encapsulation_experiments',
        restart              => false,
    }

    if $ensure_clamper == 'present' {
        exec { 'enable_tcp-mss-clamper_service':
            command => '/usr/bin/systemctl enable tcp-mss-clamper.service',
            unless  => '/usr/bin/systemctl -q is-enabled tcp-mss-clamper.service',
            require => Systemd::Service['tcp-mss-clamper'],
        }
    }

    if $firewall_provider == 'ferm' {
        $ensure_ferm_rules = $ensure
    } else {
        $ensure_ferm_rules = 'absent'
    }

    # Allow inbound IPIP && IP6IP6 traffic
    ferm::rule { 'ipip':
        ensure => $ensure_ferm_rules,
        rule   => 'saddr 172.16.0.0/12 proto ipencap ACCEPT;',
        domain => '(ip)',
    }
    ferm::rule { 'ip6ip6':
        ensure => $ensure_ferm_rules,
        rule   => 'saddr 0100::/64 proto ipv6 ACCEPT;',
        domain => '(ip6)',
    }
    # ferm based TCP MSS clamping
    $clamped_ips = $clamped_ipport.map|$ipport| {
        $ipport.match('\[?(.*)\]?:(.*)')[1]
    }.flatten().unique().sort()
    $clamped_ports = $clamped_ipport.map|$ipport| {
        $ipport.match('\[?(.*)\]?:(.*)')[2]
    }.flatten().unique().sort()

    $rule_ips = $clamped_ips? {
        Array[Stdlib::IP::Address, 1, 1] => $clamped_ips[0],
        Array                            => sprintf('(%s)', $clamped_ips.join(' ')),
    }
    $rule_ports = $clamped_ports? {
        Array[Stdlib::Port, 1, 1] => $clamped_ports[0],
        Array                     => sprintf('(%s)', $clamped_ports.join(' ')),
    }

    $outerfaces = $interfaces.join(' ')

    ferm::rule { 'clamp-mss-ipv4':
        ensure => $ensure_ferm_mss,
        chain  => 'OUTPUT',
        rule   => "outerface (${outerfaces}) saddr @ipfilter(${rule_ips}) proto tcp sport ${rule_ports} tcp-flags (SYN) SYN TCPMSS set-mss ${ipv4_mss};",
        domain => '(ip)',
    }
    ferm::rule { 'clamp-mss-ipv6':
        ensure => $ensure_ferm_mss,
        chain  => 'OUTPUT',
        rule   => "outerface (${$outerfaces}) saddr @ipfilter(${rule_ips}) proto tcp sport ${rule_ports} tcp-flags (SYN) SYN TCPMSS set-mss ${ipv6_mss};",
        domain => '(ip6)',
    }

    # monitor MSS values
    prometheus::node_lvs_realserver_mss { 'lvs_clamped_ipport':
        ensure         => $ensure,
        clamped_ipport => $clamped_ipport,
    }
    prometheus::node_ferm_mss {'ferm_clamped_ipport':
        ensure         => $ensure_ferm_mss,
        clamped_ipport => $clamped_ipport,
    }

}