Chapter 24. Two Sample FirewallsContents:Screened Subnet ArchitectureMerged Routers and Bastion Host Using General-Purpose Hardware TIP: We want to emphasize that these examples are just that: examples. You shouldn't blindly implement one of these examples without first taking the time to understand your own needs, your environment, and the implications and complications of the services you want your firewall to provide.The services that we're going to provide through these sample firewalls are just the basics: the World Wide Web, terminal access, file transfer, electronic mail, Usenet news, and DNS.
24.1. Screened Subnet ArchitectureThe screened subnet architecture, described in Chapter 6, "Firewall Architectures", and shown in Figure 24-1, is probably the most common do-it-yourself firewall architecture. This architecture provides good security (including multiple layers of redundancy) at what most sites feel is a reasonable cost.Figure 24-1. Screened subnet architectureThere are two-router and single-router variations of the screened subnet architecture. Basically, you can use either a pair of two-interface routers or a single three-interface router. The single-router screened subnet architecture works about as well as the two-router screened subnet architecture and is often somewhat cheaper. However, you need to use a router that can handle both inbound and outbound packet filtering on each interface. (See the discussion of this point in Chapter 8, "Packet Filtering".) We're going to use a two-router architecture as our example in this section because it is conceptually simpler.This type of firewall includes the following components, presented originally in Chapter 6, "Firewall Architectures":
We're going to assume (at least for the purposes of this example) that internal users in our system are trusted not to actively try to circumvent the firewall, and that there is no particular need to monitor or log their Internet activities. We're also going to assume that you are using properly assigned and routed IP addresses (that is, addresses assigned to your site and properly routed and advertised to the rest of the Internet by your service provider) for your internal and perimeter networks. If you aren't, you have to use proxies or network address translation because you can't allow packets with those unassigned IP addresses onto the Internet; even if you did allow them, replies would have no way to come back to you. Finally, we're going to assume you're using separate network numbers for your perimeter net and internal net, so that you can detect forged packets easily. (See the discussion in Section 8.6.1, "Risks of Filtering by Source Address" in Chapter 8, "Packet Filtering".) 24.1.1. Service ConfigurationGiven the architecture we've just described, how do we provide the basic Internet services?24.1.1.1. HTTP and HTTPSWe will want to provide two kinds of HTTP service. We'll want to allow our users to access other people's web sites, and we'll want to put up our own web site.For outgoing HTTP and HTTPS (letting our users access other sites), we can use either packet filtering or proxy servers. Packet filtering will allow our users to access HTTP and HTTPS servers only on standard ports; proxying will allow them to reach all HTTP and HTTPS servers. Which approach should we take? Standard browsers support HTTP and HTTPS proxying, so we don't need to worry about using customized clients with either approach. Proxying will increase configuration overhead, but that price seems fair for the increased abilities it offers. On the other hand, we could simply allow internal hosts to create connections to port 80, port 443, and any port at or above 1024. That will allow access to almost any HTTP or HTTPS server and will also be useful for supporting FTP. It does add a significant amount of risk; internal users will be able to use any protocol above 1024, with no control from the firewall. If these users are ill intentioned or even careless, they could expose the site to all sorts of dangers. In addition, any Trojan horse programs they bring in will easily be able to send out data. However, we originally chose to trust the users, so this is not an issue. Using pure packet filtering this way would lose us only servers at nonstandard ports below 1024, and those ports are all supposed to be reserved anyway. If we use a caching proxy server, we significantly improve HTTP performance for all of the following:
ost caching servers will also allow us to provide HTTP service to external sites, so we can take advantage of that to publish our site's own public web pages. This configuration is not particularly secure; the security requirements for proxying and publishing are different, and ideally we would want to separate the two. However, in a configuration with only one bastion host, we can't provide much separation in any case. Combining the proxying and publishing wouldn't be acceptable if we wanted to provide popular pages, or if we needed much security for the pages we were providing (for instance, if the web pages are used for electronic commerce). In either of those situations, we'd separate the outgoing cache from the public web server, putting them not only on different pieces of software but also on different computers. In fact, we might well choose to have the public web server on somebody else's network altogether, using a commercial web hosting service. HTTP and HTTPS proxying is also trivial to add once you have other things proxied via SOCKS or TIS FWTK. If we had SOCKS running, it would be very tempting to simply proxy through it because SOCKS is one of the systems that many of the browsers support. On the other hand, it's a lot of trouble to install SOCKS just for HTTP and HTTPS; it's probably not worth it unless we have other applications that will use it. If we used the TIS FWTK HTTP proxy, we'd have to get the users to modify URLs they use. In this case, the users wouldn't be able to cut and paste out of their electronic mail when people tell them about cool new things. Neither SOCKS nor TIS FWTK makes an attractive option in this situation. However, both proxying (through a proxying server) and packet filtering appear to be attractive and reasonable choices. Proxying is definitely preferable if we aren't going to provide passive-mode FTP directly (which gives our users the ability to talk to servers on any TCP port above 1023). On the other hand, packet filtering would definitely be preferable if we wanted to use clients that didn't come with built-in support for proxying, or if we wanted not to provide an HTTP server and had no other services being proxied. For this example, we're going to assume that we're providing HTTP and HTTPS service to internal clients via a proxy server running on the bastion host, and that we're using the same server to publish our public web pages to the world. We will take special care to make sure that the proxy component is configured to prevent external users from using the proxy to access either our internal network or other external servers. Our reasons for using a proxy server are based mostly on the added efficiency, although it's also useful to make sure that users can reach HTTP and HTTPS servers on nonstandard ports below 1023.
24.1.1.2. SMTPThere aren't many options for SMTP in any configuration. We want all external SMTP connections to go to a single machine with a secured SMTP server, and we don't trust random internal machines to have safe SMTP servers. That means we'll put a secured SMTP server on the bastion host and use DNS MX records to direct all incoming mail to the bastion host, which will then pass all the incoming mail to a single secured internal SMTP server.What other options do we have? We could put a secure SMTP server on the internal mail server and direct incoming mail to it, but if that SMTP server were compromised, the entire internal net would then be at risk. Alternatively, we could have the bastion host send mail directly to machines on the internal network, but once again, we'd be increasing our vulnerability if the SMTP server on the bastion host were compromised. The compromised bastion host would be speaking to untrustworthy internal SMTP servers, and compromise of the internal net would quickly follow. If the bastion host can speak only to the internal mail server, that narrows the possible attacks it can make; the internal mail server can run a secured SMTP server. Furthermore, by making this choice, messy maintenance tasks are transferred from the security-critical bastion host to the less vulnerable internal mail server. How about outgoing mail? It would probably be safe to allow internal machines to send mail directly to the outside world, but doing so creates a maintenance headache. (You have to watch the mail configuration on all the internal machines.) Besides, doing this opens another direct connection between the internal and external networks. There aren't any known ways for an SMTP server to attack an SMTP client, but stranger things have happened. Allowing internal machines to send mail directly to the outside world doesn't seem to bring much advantage either. The only difference it makes is that we'd be able to send mail (but not receive it) when the bastion host is down. No matter what decision we make, we'll have to configure our mail clients. (Unlike FTP and Telnet, SMTP does not work as installed without modifying configuration files.) In addition, the work to direct the mail to a server is less than the work to correctly send it to the external universe. The only real question is whether to direct the outgoing mail from the internal machines to the internal mail server or to the bastion host. Directing it to the internal mail server has the same advantages as for incoming mail and keeps internal information away from the bastion host. Mail between internal users should not go through the bastion host. We'll set up SMTP, as outlined in Chapter 16, "Electronic Mail and News", with the bastion host acting as a middleman for incoming and outgoing mail. Here's what to do:
24.1.1.3. TelnetOutgoing Telnet could be provided through packet filtering or through proxies. Which approach should we use?Proxying will require either modified clients or modified user procedures; either one will be tedious to implement. Proxying would allow us to restrict or monitor Telnet usage by user by forcing our users to authenticate to a proxy server before completing their requests. However, remember that we have decided to assume that internal users are trustworthy, so there is no need for authentication. Proxying would be necessary if we were using unassigned or unadvertised IP addresses internally, but that's not the case here either. Because we have trustworthy users and proper IP addresses, proxying for Telnet doesn't provide any advantage over packet filtering, and it's more difficult to set up and maintain. Therefore, for this example, we're going to provide outgoing Telnet via packet filtering. Incoming Telnet is considerably more difficult to provide safely and conveniently. If it were necessary, incoming Telnet could be provided on the bastion host using extra authentication. However, for a site that is looking for a simple configuration, the reasonable thing to do is to disallow incoming Telnet altogether, replacing it with SSH. That's what we'll do for this example.
24.1.1.4. SSHAlthough incoming Telnet is unsafe, it's useful to be able to allow some form of remote access. The safest way to do so is to allow SSH. One way would be to allow SSH inbound to the bastion host only, forcing users to log into the bastion host and then go from there to their internal destination; this is effectively a form of proxying. Another option would be to allow SSH inbound to any host.Forcing SSH to a single bastion host allows us to make sure that what's coming in is genuinely SSH and that the SSH server is safely configured. On the other hand, it requires us to have user accounts configured on the bastion host. If only a few users need to use SSH, it may be the best way to provide the service. However, with only a single bastion host, significant risks are involved in having user accounts around. Allowing SSH inbound to all hosts avoids the problem with user accounts on the bastion host but opens up the possibility of having hosts running SSH servers that will do port forwarding, or running other servers altogether on the SSH port. As we discuss in Chapter 18, "Remote Access to Hosts", port forwarding across SSH is a significant risk, which may make your site vulnerable to people who are attacking the client. We will allow SSH inbound to all hosts (we're already trusting internal users). For a more secure configuration, we would limit the hosts that were accessible via SSH, either by adding another bastion host on the screened network or by treating some internal hosts as screened hosts and allowing SSH to just those hosts. Since we are allowing incoming SSH, we should also allow outgoing SSH; it would be unjust to ask people to use SSH to access our site but require our users to use insecure Telnet to access other sites. However, we will want to warn our users about the risks of remote port forwarding. Unlike outgoing Telnet, outgoing SSH opens us up to incoming attacks if port forwarding is turned on. (See Chapter 18, "Remote Access to Hosts", for more information about the risks of SSH port forwarding.) For more security, we might want to limit even outgoing SSH to a machine where we could control the clients in use and disallow remote port forwarding. Note that even when SSH is limited to a single machine, it is significantly difficult to prevent users from providing their own SSH clients.
24.1.1.5. FTPUnlike Telnet, FTP doesn't lend itself to a pure packet filtering solution. Because normal-mode FTP requires an incoming connection to an arbitrary port over 1023, trying to allow it without doing anything else gives attackers access to all kinds of services running on our internal systems. That leaves us two choices:
A reasonable compromise would be to use both packet filtering and proxies, using a proxying gateway like ftp-gw from TIS FWTK that doesn't require modification of the clients. Clients that support passive mode will work via the packet filters. On platforms where we can easily replace the provided clients, we can provide passive-mode clients; on platforms where we can't easily replace the clients, we can modify user procedures instead. As we've said, if we wanted to monitor FTP usage, we'd have to use proxying exclusively, but that's not the case here. If we were using an unassigned or unrouted network number, we'd have to do either proxying or network address translation. We also might want to use proxying exclusively if we decided to hide DNS data -- it would save us the trouble of faking data for double-reverse lookups by using a published address with an advertised reverse mapping -- but hiding DNS data is more trouble than it's worth. In a situation where proxying is used exclusively, we'd have to reconsider which proxy server to use. The proxy server we've selected requires users to modify their procedures, which makes sense in the configuration we're discussing because there are no other options. The balance might come out differently if everybody were proxying. Be aware that in order to use the TIS FWTK ftp-gw proxy server on your bastion host, your packet filtering will have to allow TCP connections from ports above 1023 on your bastion host to ports above 1023 on internal hosts, and from port 20 on external hosts to ports above 1023 on your bastion host, for FTP data channels. (See the discussion of FTP in Chapter 17, "File Transfer, File Sharing, and Printing".) This means that someone who breaks in to the bastion host could easily connect to any server on any internal host that uses a TCP port above 1023 (for example, an X11 server on port 6000). Further, any servers that are using such ports (that is, TCP ports above 1023) on the bastion host itself are also vulnerable. For this reason, if you allow these FTP data connections at all for proxying, you probably want to explicitly block access to internal systems to TCP ports above 1023 where you know, or have good cause to suspect, that servers might be listening. At the very least, the ports you want to block probably include 6000 through around 6003 (assuming four or fewer real or virtual X11 servers per machine; see the discussion of X11 in Chapter 18, "Remote Access to Hosts"). Since we're allowing SSH, we also need to protect the virtual X11 servers that SSH creates, which start at 6010, so we'll extend this port range to 6020. Keep in mind, however, that blocking specific ports, rather than blocking all ports by default and then allowing specific ports, is generally a dangerous strategy. It's hard to develop and maintain a complete list of ports that need to be blocked at your site. It would be better to block everything by default and then allow only specific ports, but you can't do that with standard (nonpassive) FTP because of the way it works. Allowing passive-mode FTP with packet filtering is a fairly liberal approach because it allows pretty much any connection to go through as long as it is initiated by the inside. The number of servers above port 1023 is very large. This has some advantages (it lets users access nonstandard HTTP servers, for example), but it may also allow users to access all kinds of services that are unsafe. In allowing it, we're assuming that our users are not only well intentioned, they're also capable of telling the difference between a safe and an unsafe connection, or at least avoiding the temptation to do unexpected things. Because we've denied incoming Telnet, it makes sense to deny incoming user FTP as well. Both services require approximately the same security measures, and making one of them available would make configuring the other trivial. Incoming anonymous FTP is a different matter, and we'll provide it. Because we're not a major Internet service provider, and because we're using TIS FWTK already anyway, we can go for security over features and use the TIS FWTK anonymous FTP server. If we were going to provide major anonymous FTP, we'd probably want to use the more feature-filled wuarchive FTP server (see Chapter 17, "File Transfer, File Sharing, and Printing", for a description of its capabilities) and run it on a machine that was not the main bastion host but that was still a bastion host on the perimeter network. Using another bastion host avoids overloading the main bastion host with risky and interacting services.
24.1.1.6. NNTPAs we've discussed in Chapter 16, "Electronic Mail and News", the most practical way to set up NNTP across a firewall is to allow your NNTP service provider(s) to talk directly to your internal Usenet news host, and vice versa. We'd need an overwhelming reason to do something else, and it's hard to imagine one. Even if we didn't have an existing internal news host, building one isn't any harder than building a news server on the bastion host, and it's safer by a vast margin. News servers fail with dreary regularity; while the problems usually aren't security-related, you still don't want to install anything requiring high maintenance on a bastion host.For this example, we're going to assume a single external NNTP newsfeed.
24.1.1.7. DNSAs discussed in Chapter 20, "Naming and Directory Services", DNS is best provided across a firewall with a pair of servers: one on the bastion host, the other on an internal host. Like NNTP, DNS presents a situation in which the number of rational solutions is clearly limited. We need to decide whether to use separate internal and external servers to do information hiding, or whether we should allow the external world to see all of our host data. By deciding to allow direct passive-mode FTP, we've already made that decision indirectly. Direct passive-mode FTP would require intricate DNS setup to support information hiding and still provide valid data for the internal hosts that are FTP clients.For this example, we're going to assume that the DNS server on the bastion host is a secondary server for our domain, and that the primary server is on an internal host. We're not going to do any DNS information hiding.
24.1.2. Packet Filtering RulesBased on the configuration decisions we've made in the previous sections, let's look at the packet filtering rules necessary to support this configuration. We assume an "ideal" router (as discussed in "Choosing a Packet Filtering Router" in {XREF}). If our router were less than ideal in terms of capabilities, we'd need to modify these rules accordingly, probably at the cost of security. We might have to rethink several crucial decisions entirely. For example, if we couldn't filter on the ACK bit, direct outbound passive-mode FTP would no longer be acceptably safe, and a lot of our other decisions have used that as a major factor. (See Chapter 8, "Packet Filtering" for a full discussion of packet filtering capabilities and the implications of not having particular capabilities.)In the packet filtering rules presented in the following table, we assume that the filtering system:
TIP: In the following table, directions are shown relative to the site, as they have been in previous tables. 24.1.2.1. Interior routerThe purpose of the interior router is to protect the internal network from the Internet and from your own bastion host. The interior router needs the following rules to support the outlined configuration. Explanations of each rule follow the table.
[180]UDP has no ACK equivalent. Here is some additional information about each set of rules in this table:
24.1.2.2. Exterior routerThe purpose of the exterior router is twofold:
The differences between the rules for the interior router and the exterior router all have to do with the bastion host. That's because the bastion host sits "outside" of the interior router (i.e., on the side of the interior router towards the Internet), but it sits "inside" of the exterior router (i.e., on the side of the exterior router away from the Internet). If you can set up filtering on the exterior router, it's a good idea to do so. If nothing else, it can serve as a backup to some of the filtering on the interior router. For this example, you would need to establish the following rules.
[181]UDP has no ACK equivalent. Here is some additional information about each set of rules in this table:
24.1.3. Other Configuration WorkIn addition to setting up the packet filtering rules, we need to do various other kinds of configuration work, as follows:
24.1.4. AnalysisJust how good a firewall is this one we've configured? Let's consider it in relation to the strategies and principles discussed in Chapter 3, "Security Strategies".24.1.4.1. Least privilegeThe principle of least privilege is that an object (a program, a person, a router, or whatever) should have the minimum privileges necessary to perform its assigned task and no more. A corollary of this principle is that systems should be configured so they require as little privilege as possible. You can see this principle in action in several places in this setup. For example, configuring SMTP so that outgoing mail goes out via the bastion host (rather than directly to remote systems) is an application of least privilege because it lets you control more tightly how internal systems connect to external systems. (In this case, it makes it unnecessary for internal systems to talk directly to external systems in order to provide this service.)
24.1.4.2. Defense in depthThe principle of defense in depth is something else that you can see in the setup we've described. For example, internal hosts are protected from the outside world by the exterior and interior routers. Similarly, the bastion host is protected against attack both by its own careful configuration and by the exterior router.Several times, we've explicitly made decisions to increase the depth of defense. For example, that's one of the main purposes of using an internal mail server between the bastion host and the internal clients. The interior and exterior routers often deny the same packets. Defense in depth is almost the only reason for having the interior router deny packets that it supposedly can't receive (because they've already been denied by the exterior router).
24.1.4.3. Choke pointThe principle of a choke point is clearly applied in our setup because everything between internal clients and the Internet comes through the perimeter net. Further, much of it comes through the bastion host via proxies. Only Telnet, SSH, and FTP are provided in ways that leave them relatively open. These services could have been better choked by using proxies everywhere.
24.1.4.4. Weakest linkThere is no single obvious weak link to attack in this configuration. Probably the weakest link is the bastion host, but even a completely compromised bastion host isn't going to help an attacker much when it comes to attacking the internal systems; not that many connections are allowed from the bastion host to internal systems. Some of the weakest links you can see remaining in this setup include incoming SSH, proxy FTP, combining a public HTTP server with the outgoing caching proxy server.Allowing inbound SSH to every host is another candidate for the weakest link; it is the point where we put the most trust in the users. Users who choose poor passwords or set up SSH tunnels can easily undermine the security of the firewall. This could be strengthened significantly by restricting SSH to a dedicated bastion host, which could help enforce password and tunneling restrictions. Users could still connect from that host to internal hosts. The proxy FTP setup we've described would allow an attacker who has compromised the bastion host to attack servers on ports above 1023 (if there are any) on internal hosts. How can you address this vulnerability? Obtain and use only passive-mode FTP clients internally, don't run proxy FTP, and remove the rules allowing proxy FTP from the filters. Combining incoming and outgoing HTTP service has several drawbacks. First, the server program itself is more complicated; it is trying to enforce different restrictions for internal and external users, and bugs or misconfigurations may inappropriately mix the two, allowing external users to use the server to attack internal machines or third parties. Second, public HTTP servers attract attackers, who you do not want to concentrate on a machine that is important to your site's functioning. You could address this problem by moving the public HTTP server to a dedicated machine, or even using an outside web hosting service to remove it from your site altogether. As discussed in Chapter 3, "Security Strategies", there are two reasons for knowing what the weakest links in your firewall are. The first reason is so that you can fix them, if possible; we've already talked about things you might change in this firewall to strengthen some of the weak links. The second reason is so that you can monitor those links which you cannot eliminate for one reason or another. For instance, to address the risks posed by allowing SMTP from the bastion host to the internal mail server, you can't practically disallow incoming SMTP; that would cut off incoming mail from the outside world, which probably isn't appropriate. Since you can't eliminate that weak link, you should instead monitor it closely to make sure that an attacker doesn't take advantage of it (i.e., you should monitor the internal mail server for attacks from the bastion host via SMTP, by monitoring the SMTP logs and reports on the internal mail server). You can keep playing the game of thinking "If I were an attacker, what would I do?" and then addressing the problems you discover ad nauseam, or until you run out of time or money. At some point, though, you (or your management) will probably decide you've done enough (based on your own site's definition of "enough").
24.1.4.5. Fail-safe stanceYou can see the principle of a fail-safe stance applied through the packet filtering rules. In general, the rules specify what you're going to allow and deny everything else by default. This is a fail-safe approach because if something unanticipated comes along (a new service, for example), it won't be allowed through your firewall, unless, of course, it mimics or is tunneled through some other service you do allow. The redundant router rules also provide a fail-safe against failure of one router or the other. If filtering accidentally or temporarily gets turned off on one router (causing it to pass all packets), the other still does most of the same filtering, at least as far as the outside world is concerned.
24.1.4.6. Universal participationIf this is our site's only connection to the Internet, we have involuntary universal participation; everybody has to go through the firewall to get to the Internet. Of course, we'd be much better off with voluntary universal participation, but that may require some user education about the goals of and the need for the security measures we're adopting.To some extent, we're relying on voluntary universal participation. We've granted free Telnet, SSH, and FTP access, and in the process, we've allowed any outbound connection to ports at or above 1024 (which is plenty of rope for the users to hang us with). FTP is by no means the only service above 1024. In particular, we've assumed that this is your sole connection to the Internet and that internal users aren't just going to bypass the firewall entirely by setting up their own Internet connections. All it takes is one joker with a modem, a PPP software package, and an outside phone line, and you too could have an unprotected back door into your network.
24.1.4.7. Diversity of defenseThere are opportunities in this configuration to apply the principle of diversity of defense (e.g., using routers from different vendors for the interior and exterior packet filtering systems). Most sites will probably conclude that such an approach is not worth the hassle. However, even if you use similar or identical hardware, you still might get some diversity by having different people do at least the initial configuration of the different filtering systems, and then having them cross-check each other's work.Using different SMTP servers on the internal mail server and the bastion host would be a fairly major advance in this configuration because that's one of the main weak points of this setup. Even a less secure but different SMTP server on the internal mail server is arguably better than one that's going to yield to the exact same attack that just succeeded on the bastion host. The more vulnerable the SMTP server you're using, the more important an issue this is.
24.1.4.8. SimplicitySimplicity is another important security strategy. This particular firewall configuration provides simplicity by separating components so that each component is as simple and comprehensible as possible. We've made a number of decisions specifically to simplify the configuration; for example, the decision to use separate interior and exterior routers (rather than a single three-interface router) simplifies the packet filtering rules and makes them easier to understand.
24.1.5. ConclusionsA lot of advantages are offered by a scheme such as the one we've described in the previous sections. The main potential disadvantages we can see are cost and complexity; but we don't think that the configuration we've presented is too expensive for most sites, and we think that it presents the minimum necessary level of complexity.What if you really need to save some money? It would be feasible to construct a screened subnet architecture using a single three-interface router, instead of the pair of two-interface routers we've described. The solution would be a little more complex because you'd have to merge the two separate filtering sets described previously, but doing so shouldn't be too difficult. It would also be relatively easy to construct a more secure configuration with the same basic architecture. A less trusting site would force all Telnet, SSH, and FTP through proxies, which would allow much better logging and remove the nagging holes created by allowing every outbound connection to ports above 1024. Once you force the extra protocols through proxies, you'd also find that DNS information hiding would be both more practical and more reasonable. However, the price of this increased security would be a more complex and fragile configuration, and one that presents more annoyance to the users. It would also be possible to increase the services offered without major architecture changes. For example, incoming Telnet and incoming user FTP could be supported relatively easily for a few users on the bastion host or on a dedicated host on the screened network. Serious anonymous FTP service or HTTP service could be provided by configuring extra machines on the screened network. Similarly, you could scale up the firewall to support a second Internet connection or redundant bastion hosts to provide more reliable service or service for a much larger internal network.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|