GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( ca105e...9d9c7b )
by François
02:33
created

Firewall::getForwardFirewall()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 19
rs 9.2
cc 4
eloc 11
nc 2
nop 2
1
<?php
2
/**
3
 * Copyright 2016 François Kooman <[email protected]>.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace fkooman\VPN\Server;
19
20
class Firewall
21
{
22
    public static function getFirewall4(Pools $p, $asArray = false)
23
    {
24
        return self::getFirewall($p, 4, $asArray);
25
    }
26
27
    public static function getFirewall6(Pools $p, $asArray = false)
28
    {
29
        return self::getFirewall($p, 6, $asArray);
30
    }
31
32
    private static function getFirewall(Pools $p, $inetFamily, $asArray)
33
    {
34
        $firewall = [];
35
36
        // NAT
37
        $firewall = array_merge($firewall, self::getNat($p, $inetFamily));
38
39
        // FILTER
40
        $firewall = array_merge($firewall, self::getFilter($p, $inetFamily));
41
42
        if ($asArray) {
43
            return $firewall;
44
        }
45
46
        return implode(PHP_EOL, $firewall).PHP_EOL;
47
    }
48
49
    private static function getNat(Pools $p, $inetFamily)
50
    {
51
        $nat = [
52
            '*nat',
53
            ':PREROUTING ACCEPT [0:0]',
54
            ':INPUT ACCEPT [0:0]',
55
            ':OUTPUT ACCEPT [0:0]',
56
            ':POSTROUTING ACCEPT [0:0]',
57
        ];
58
59
        foreach ($p as $pool) {
60
            if ($pool->getUseNat()) {
61
                if (4 === $inetFamily) {
62
                    // get the IPv4 range
63
                    $srcNet = $pool->getRange()->getAddressPrefix();
64
                } else {
65
                    // get the IPv6 range
66
                    $srcNet = $pool->getRange6()->getAddressPrefix();
67
                }
68
                $nat[] = sprintf('-A POSTROUTING -s %s -o %s -j MASQUERADE', $srcNet, $pool->getExtIf());
69
            }
70
        }
71
        $nat[] = 'COMMIT';
72
73
        return $nat;
74
    }
75
76
    private static function getFilter(Pools $p, $inetFamily)
77
    {
78
        $filter = [
79
            '*filter',
80
            ':INPUT ACCEPT [0:0]',
81
            ':FORWARD ACCEPT [0:0]',
82
            ':OUTPUT ACCEPT [0:0]',
83
        ];
84
85
        // INPUT
86
        $filter = array_merge($filter, self::getInputChain($p, $inetFamily));
87
88
        // FORWARD
89
        $filter = array_merge($filter, self::getForwardChain($p, $inetFamily));
90
91
        $filter[] = 'COMMIT';
92
93
        return $filter;
94
    }
95
96
    private static function getInputChain(Pools $p, $inetFamily)
97
    {
98
        $inputChain = [
99
            '-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT',
100
            sprintf('-A INPUT -p %s -j ACCEPT', 4 === $inetFamily ? 'icmp' : 'ipv6-icmp'),
101
            '-A INPUT -i lo -j ACCEPT',
102
        ];
103
104
        $inputPorts = self::getIngressPorts($p);
105
        foreach ($inputPorts as $inputPort) {
106
            list($proto, $port) = explode('/', $inputPort);
107
            $inputChain[] = sprintf('-A INPUT -m state --state NEW -m %s -p %s --dport %d -j ACCEPT', $proto, $proto, $port);
108
        }
109
110
        $inputChain[] = sprintf('-A INPUT -j REJECT --reject-with %s', 4 === $inetFamily ? 'icmp-host-prohibited' : 'icmp6-adm-prohibited');
111
112
        return $inputChain;
113
    }
114
115
    private static function getForwardChain(Pools $p, $inetFamily)
116
    {
117
        $forwardChain = [
118
            '-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT',
119
        ];
120
121
        foreach ($p as $pool) {
122
            if (6 === $inetFamily && !$pool->getForward6()) {
123
                // IPv6 forwarding was disabled
124
                continue;
125
            }
126
127
            if (4 === $inetFamily) {
128
                // get the IPv4 range
129
                $srcNet = $pool->getRange()->getAddressPrefix();
130
            } else {
131
                // get the IPv6 range
132
                $srcNet = $pool->getRange6()->getAddressPrefix();
133
            }
134
            $forwardChain[] = sprintf('-N vpn-%s', $pool->getId());
135
136
            $forwardChain[] = sprintf('-A FORWARD -i tun-%s+ -s %s -j vpn-%s', $pool->getId(), $srcNet, $pool->getId());
137
138
            // merge outgoing forwarding firewall rules to prevent certain
139
            // traffic
140
            $forwardChain = array_merge($forwardChain, self::getForwardFirewall($pool, $inetFamily));
141
142
            if ($pool->getClientToClient()) {
143
                // allow client-to-client
144
                $forwardChain[] = sprintf('-A vpn-%s -o tun-%s+ -d %s -j ACCEPT', $pool->getId(), $pool->getId(), $srcNet);
145
            }
146
            if ($pool->getDefaultGateway()) {
147
                // allow traffic to all outgoing destinations
148
                $forwardChain[] = sprintf('-A vpn-%s -o %s -j ACCEPT', $pool->getId(), $pool->getExtIf(), $srcNet);
149
            } else {
150
                // only allow certain traffic to the external interface
151
                foreach ($pool->getRoutes() as $route) {
152
                    if ($inetFamily === $route->getFamily()) {
153
                        $forwardChain[] = sprintf('-A vpn-%s -o %s -d %s -j ACCEPT', $pool->getId(), $pool->getExtIf(), $route->getAddressPrefix());
154
                    }
155
                }
156
            }
157
        }
158
159
        $forwardChain[] = sprintf('-A FORWARD -j REJECT --reject-with %s', 4 === $inetFamily ? 'icmp-host-prohibited' : 'icmp6-adm-prohibited');
160
161
        return $forwardChain;
162
    }
163
164
    private static function getForwardFirewall(Pool $pool, $inetFamily)
165
    {
166
        $forwardFirewall = [];
167
168
        if ($pool->getBlockSmb()) {
169
            // drop SMB outgoing traffic
170
            // @see https://medium.com/@ValdikSS/deanonymizing-windows-users-and-capturing-microsoft-and-vpn-accounts-f7e53fe73834
171
            foreach (['tcp', 'udp'] as $proto) {
172
                $forwardFirewall[] = sprintf(
173
                    '-A vpn-%s -o %s -m multiport -p %s --dports 137:139,445 -j REJECT --reject-with %s',
174
                    $pool->getId(),
175
                    $pool->getExtIf(),
176
                    $proto,
177
                    4 === $inetFamily ? 'icmp-host-prohibited' : 'icmp6-adm-prohibited');
178
            }
179
        }
180
181
        return $forwardFirewall;
182
    }
183
184
    private static function getIngressPorts(Pools $p)
185
    {
186
        $ingressPorts = ['tcp/22', 'tcp/80', 'tcp/443'];
187
188
        // we only care about additional UDP ports, as we only want UDP and
189
        // fallback to tcp/443
190
        foreach ($p as $pool) {
191
            foreach ($pool->getInstances() as $instance) {
192
                if ('udp' === $instance->getProto()) {
193
                    $port = sprintf('udp/%d', $instance->getPort());
194
                    if (!in_array($port, $ingressPorts)) {
195
                        $ingressPorts[] = $port;
196
                    }
197
                }
198
            }
199
        }
200
201
        return $ingressPorts;
202
    }
203
}
204