要するに:
- cfnetwork-ネットワークを完全に構成し、PuppetリソースをフィルタリングするためのPuppet API。 Hieraと、Puppetコンセプトの他の「データプロバイダー」との完璧な友達。
- cffirehol-素晴らしいFireHOLジェネレーターに基づいた
cfnetwork
のフィルター設定の特定の実装の「メタプロバイダー」- これまでのところ、Debian 8+(Jessie以上)およびUbuntu 14.04+(Trusty以上)のみがサポートされています
テーマサイクル:
- パートI:ネットワークおよびネットワークフィルター(cfnetwork + cffirehol)
- パートII:アクセスと標準環境(cfauth + cfsystem)
- パートIII:Puppet Server(cfpuppetserver)のインストール
- パートIV:集中管理(cftotalcontrol)
- パートV:データベース(cfdb)
- パートVI:現在のブラックリストと保護されたノッキング
叙情的な紹介: 展開されたシステムの監視と自動化のトピックについて、著者が非常に妄想していることが起こりました。 長年にわたり、遭遇した問題の経験と比較的小さな町の解決策が蓄積されました。 私の以前の職場を離れた後、管理領域に具体的な手荷物がないことが明らかになりました。 しかし、私は本当に隣にあるものをドラッグしたくありませんでした。 そこで新しい自転車が誕生しました。 ここまでがポイントです。
注:テキスト全体で、作成者の壊れやすい子供の聴覚、目、脳をレイプする他の「ロシア語」という用語
代わりに、意図的に
または
使用されます。
既存のソリューションに適さないものは何ですか?
- ネットワーク構成とサージプロテクターの弱い統合 -(再)構成とエラーのリスクが高いことによる追加の騒ぎ; セキュリティシステムと友達である個々のサービスのプラグアンドプレイモジュールを作成するのが難しい。
- 監査のための可視性の欠如 -構成は簡潔ではなく、多くのファイルに広がっているか、人にとっては読めない方法で存在しています。
- 抽象化のない過度に低レベルのフィルター構成は、上記のポイントと同じ問題です。 これは、アセンブラーでWebページを作成することと比較できます。
- デフォルト設定の「インテリジェンス」の欠如 -不器用な人にとっては利点ですが、著者にとってはそうではありません。
- 通常、ネットワークスタックのチューニングはバイパスされます。バニラカーネルの設定は、セキュリティは言うまでもなく、テストや最適化の前であっても戦闘システムで見たいものとはほど遠いものです。
ネットワークおよびフィルター設定の一般的な概念
新しい理論はありません-別の場所からのルーチン。
- 各論理ネットワークインターフェイスには、
world
、dmz
、office
などの一意の意味のある名前がありworld
。local
loopback
インターフェイス用に予約されています。 - 標準の論理インターフェイスの設定が設定され、フィルタールールジェネレーターからアクセス可能になります。
- 特別なタイプのインターフェイス
any
サポート-フィルタージェネレーターは、決して機能しない不必要なルールを生成しないように十分にスマートでなければなりません。 たとえば、許可されたアドレスのリストが発信または着信のものに指定されている場合、そのような接続が原則としてネットワーク構成によって想定されていないインターフェースにルールを追加しないでください。 - ポートを直接指定する代わりに、連想名が使用され、ポートとプロトコルのセット全体を隠すことができます。
- ネットワークとフィルターの一時的な調整は、障害からの回復中に集中管理することなく、ターゲットマシンで簡単に実行する必要があります。
- AppArmorまたはSeLinuxをオンにする前に、適切なネットワークセキュリティを実現する必要があります。
- 動的保護は個別に実装する必要がありますが、ブラックリストインターフェイスはこのレベルで設定されます。
技術の選択
- Puppet 4 + Puppet DB + Hiera-著者は正直にAnsibleとChefの少なくとも1つに愛を植え付けようとしましたが、Puppetの4番目のバージョンが犠牲になりました。 ただし、Ansibleは定期的なメンテナンスタスクとPuppetの初期展開には興味深いようです。
- 基本的に、 RubyはPuppet拡張機能の定義済みの選択肢です。 ところで、著者はプロジェクト中にこのPLを研究しなければなりませんでしたが、彼はまったく後悔していません。
- FireHOLは、 作成者が10年以上のアクティブなサーバー管理のためにネットワークフィルターを委託することができた最初のサードパーティの
iptables
ジェネレーターです。 他のすべてのジェネレーターは主観的にフェードします。
どうした
インターフェイス自体は、メインのcfnetwork
クラスと、ネットワーク設定とネットワークフィルターを指定するcfnetwork::*
タイプのセットで構成されています。 すべての設定は、Puppet DSLまたはHieraなどのデータプロバイダーを介してプログラムで設定できます。
不完全なパラメーターのリストを含むAPIの簡単な説明。 完全版は英語で入手できます。
cfnetwork
クラス
-
main
-cfnetwork::iface
設定cfnetwork::iface
メインインターフェイスのcfnetwork::iface
。 -
dns
-DNSサーバーのリストまたは特別な値:
-
'$recurse'
ローカルサーバーを配置します。 -
'$serve'
は同じですが、$service_face
顧客にサービスを提供しています。
-
-
is_router
このマシンはネットワークルーターとして機能しますか? -
optimize_10gbe
デフォルトのTCP設定を調整し、50〜100ミリ秒の推定遅延でパブリック「インターネット」の代わりに10 + Gbitインターフェースを介して最大接続パフォーマンスを実現します。 - Hieraを使用する便利さ。
ifaces
を除くすべての値にはlookup_options: { merge: hash }
(documentation)があります。
-
ifaces
-cfnetwork::iface
ようなセカンダリインターフェイスの設定のセット。 -
describe_services
-cfnetwork::describe_service
(サービスの説明)のリソースの説明のセット。 -
service_ports
-set *cfnetwork::service_port
(着信接続)。 -
client_ports
-set *cfnetwork::client_ports
(送信接続)。 -
dnat_ports
-set *cfnetwork::dnat_ports
。 -
router_ports
-set *cfnetwork::router_ports
。
-
タイプcfnetwork::iface
インターフェイス設定。
-
title
他のリソースで使用される連想識別子。 -
device
-システムネットワークインターフェイス。 -
"address/cidr"
形式のネットワークマスクと一緒のメインIPv4 / IPv6アドレス。 -
extra_addresses
同じ形式の追加アドレス。 -
extra_routes
追加のルーティング設定(フィルタージェネレーターにとっても重要)。 -
gateway
-フィルタージェネレーターで使用されるデフォルトの行進を意味します。 -
force_public = auto
は、フィルターの非常に重要な設定です。
- デフォルトでは、
$address
が10 / 8、172.16 / 12または192.168 / 16に属する場合はfalse
、そうでない場合はtrue
です。 -
true
:
- アウトバウンド接続用にSNATまたはMASQUERADEを自動的に追加します。
- DNATを含むインバウンド接続のTCP SYNPROXYを自動的に有効にします 。
- デフォルトで
REJECT
代わりにDROP
ポリシーを配置します。 - 着信pingを1 /秒に制限します。 1つのIPのハッシュ制限を介して。
- 特別なホワイトリストを除き、着信IPのグローバルブラックリストを設定します。
- デフォルトでは、
タイプcfnetwork::describe_service
サービスの説明(プロトコルとポート)。
-
title
すべてのポート名にリソースの名前が使用されます。 -
server
-proto/portnum
のサーバーポートのリスト。 例:[ 'tcp/80', 'tcp/443' ]
。
タイプcfnetwork::client_port
発信接続の説明。
FireHOLから取られた用語..
-
title = '<iface>:<service>[:<tag>]'
-
src
、dst
、user
、group
、comment
タイプcfnetwork::service_port
着信接続の説明。
-
title = '<iface>:<service>[:<tag>]'
-
src
、dst
、comment
タイプcfnetwork::router_port
許可されたルーティング可能な接続の説明。
-
title = '<iface>/<outface>:<service>[:<tag>]'
-
src
、dst
、comment
タイプcfnetwork::dnat_port
同時にルーティングされる接続と宛先アドレスの変換の説明
-
title = '<iface>/<outface>:<service>[:<tag>]'
-
src
、dst
、comment
-
to_dst
リダイレクトアドレス(IPv4およびIPv6) -
to_port
リダイレクトポート(オプション)
統一されたパラメーターの説明:
-
<iface>
-関連付けられたリソースの名前cfnetwork::iface
または:
-
'local'
-前述のように、ローカルトラフィックのみ。 ただし 、 外部IPへのトラフィックもlocal
を通過することに注意してください。 -
'any'
は、明らかに未使用のルールを作成しないように、src
、dst
、およびto_dst
基づく特別な複雑なログインです。 これらのパラメーターが存在しない場合、すべての可能なインターフェイスに追加されます。 (たとえば、local
はrouter_port
では意味がありません)
-
-
<outface>
は同じですが、dnat_port
とrouter_port
場合の2番目のインターフェース用 -
<service>
cfnetwork::describe_service
のサービス記述の名前cfnetwork::describe_service
-
<tag>
はオプションの部分であり、comment
ます。
「仮想リソース」を明示的に使用する必要なく、リソース名の競合を回避するために追加されました -
src
、dst
発信およびターゲットIPv4 / IPv6アドレスのリスト -
comment
-任意の1行コメント(改行は強制的にカットされます) -
user
、group
-発信接続のユーザーとグループを確認します(実際の偏執病者は、local
もそれらを使用する必要があります)
クラスcfnetwork::sysctl
ネットワークスタックを微調整する機能。標準キーはクラスパラメーターの形式で表示されます。
cffirehol
クラス-フィルタージェネレーター
-
enable=false
フィルター設定が期待通りであることを確認した後、強制的に有効にする必要があります -
synproxy_public=true
true-パブリックインターフェイスでSYNPROXYフラグを有効にします -
ip_whitelist
/ip_blacklist
静的リスト。 ここではip_blacklist
を設定すべきではありませんが、絶えず更新されるデータベースと動的保護システムから動的にipset
に詰め込む必要がありますが、これは別の話です。
定義済みキット:
-
whitelist4
およびwhitelist6
-IPv4およびIPv6whitelist6
ネットワーク -
blacklist4
個々のIPv4blacklist4
アドレス -
blacklist4net
およびblacklist6net
-IPv4およびIPv6blacklist6net
ネットワーク
-
DebianおよびUbuntuには十分な新しいFireHOLパッケージがなく、標準のパッケージはネットワークインターフェイスを上げた後にのみ起動されるため、.debパッケージをビルドする必要がありました。
注: cfxxx
シリーズの各Puppetモジュールの説明cfxxx
は、「暗黙的に作成されたリソース」というセクションcfxxx
、定義されているすべてのネットワークフィルターリソースについて説明しています。
生きている例
この記事で取り上げていないモジュールを使用したVagrantでのインフラストラクチャの完全な展開については、 こちらをご覧ください 。
明確にするために、ルーターのネットワーク構成とフィルターを示します。
ヒエラ設定
classes: - cfnetwork # , `/sbin/firehol try` #cffirehol::enable: true cfnetwork::is_router: true cfnetwork::main: device: eth1 address: '192.168.1.30/24' extra_addresses: '192.168.1.40/24' gateway: '192.168.1.1' # force_public: true cfnetwork::ifaces: vagrant: device: eth0 method: dhcp # extra_routes: ['10.0.1.1/25'] infradmz: device: eth2 address: '10.10.1.254/24' dbdmz: device: eth3 address: '10.10.2.254/24' webdmz: device: eth4 address: '10.10.2.254/24' cfnetwork::describe_services: testdb: server: 'tcp/1234' cfhttp: server: - 'tcp/80' - 'tcp/443' # DNAT HTTP ( ) cfnetwork::dnat_ports: 'main/webdmz:cfhttp': dst: '192.168.1.40' to_dst: '10.10.2.10' cfnetwork::router_ports: # NTP, DNS, APT 'infradmz/main:cfhttp:apt': src: 'maint.example.com' 'infradmz/main:ntp': src: 'maint.example.com' # Puppet Server (r10k) 'infradmz/main:cfhttp:puppet': {} # DMZ 'any/infradmz:ntp': src: '10.10.0.0/16' dst: 'maint.example.com' 'any/infradmz:dns': src: '10.10.0.0/16' dst: 'maint.example.com' 'any/infradmz:aptproxy': src: '10.10.0.0/16' dst: 'maint.example.com' 'any/infradmz:puppet': src: '10.10.0.0/16' dst: 'puppet.example.com' # 'webdmz/dbdmz:testdb': {}
生成されたフィルタージェネレーターの構成(これが行われます)
はい、冗長性の割合はわずかですが、将来のバージョンでは最適化を実行できます。 たとえば、2つのルールを設定しても意味がありません。1つは他のルールの特定のケースです。 原則として、生成コードは、実装時に多くの「知的」条件ですでに大きくなりすぎています。
この構成は、 cffirehol::enable=true
ときに自動的にcffirehol::enable=true
!
# This file is autogenerated by cffirehol Puppet Module # Any changes made here may be overwritten at any time version 6 # Defaults #---------------- DEFAULT_INTERFACE_POLICY="DROP" DEFAULT_ROUTER_POLICY="DROP" FIREHOL_LOG_MODE="NFLOG" FIREHOL_TRUST_LOOPBACK="0" FIREHOL_DROP_ORPHAN_TCP_ACK_FIN="1" FIREHOL_INPUT_ACTIVATION_POLICY="DROP" FIREHOL_OUTPUT_ACTIVATION_POLICY="DROP" FIREHOL_FORWARD_ACTIVATION_POLICY="DROP" # Custom Services #---------------- server_dns_ports="tcp/53 udp/53" client_dns_ports="any" # Use to open all TCP ports (eg for local) server_alltcp_ports="tcp/1:65535" client_alltcp_ports="any" # Use to open all UDP ports (eg for local) server_alludp_ports="udp/1:65535" client_alludp_ports="any" # Use to open all TCP and UDP ports (eg for local) server_allports_ports="udp/1:65535 tcp/1:65535" client_allports_ports="any" server_cfhttp_ports="tcp/80 tcp/443" client_cfhttp_ports="default" server_testdb_ports="tcp/1234" client_testdb_ports="default" server_cfssh_ports="tcp/22" client_cfssh_ports="default" server_smtp_ports="tcp/25" client_smtp_ports="default" server_cfsmtp_ports="tcp/25 tcp/465 tcp/587" client_cfsmtp_ports="default" server_puppet_ports="tcp/8140" client_puppet_ports="default" # Setup of ipsets #---------------- ipset4 create whitelist4 hash:net ipset6 create whitelist6 hash:net ipset4 create blacklist4 hash:ip ipset4 create blacklist4net hash:net ipset6 create blacklist6net hash:net # note: hardcoded list is not expected to be large ipset4 add whitelist4 "10.0.0.0/8" # Protection on public-facing interfaces #---------------- # main blacklist4 input inface "eth1" ipset:blacklist4net ipset:blacklist4 except src ipset:whitelist4 blacklist6 input inface "eth1" ipset:blacklist6net ipset:blacklist6 except src ipset:whitelist6 iptables -t raw -N cfunroute_main iptables -t raw -A cfunroute_main -s "10.0.0.0/8,172.16.0.0/12,224.0.0.0/4,127.0.0.1/8" -j DROP iptables -t raw -A cfunroute_main -d "10.0.0.0/8,172.16.0.0/12,224.0.0.0/4,127.0.0.1/8" -j DROP iptables -t raw -A PREROUTING -i "eth1" -j cfunroute_main # cfauth: synproxy4 input inface main dst "192.168.1.30/24" dport "22" src "192.168.0.0/16" accept synproxy4 forward inface main dst "192.168.1.40" dport "80" dnat to "10.10.2.10" synproxy4 forward inface main dst "192.168.1.40" dport "443" dnat to "10.10.2.10" iptables -t nat -N cfpost_snat_main iptables -t nat -A cfpost_snat_main -s 192.168.1.30,192.168.1.40 -j RETURN iptables -t nat -A cfpost_snat_main -j SNAT --to-source=192.168.1.30 iptables -t nat -A POSTROUTING -o "eth1" -j cfpost_snat_main # vagrant blacklist4 input inface "eth0" ipset:blacklist4net ipset:blacklist4 except src ipset:whitelist4 blacklist6 input inface "eth0" ipset:blacklist6net ipset:blacklist6 except src ipset:whitelist6 # cfauth: iptables -t nat -A POSTROUTING -o "eth0" -j MASQUERADE # Custom Headers #---------------- # NAT #---------------- dnat4 to "10.10.2.10" inface "eth1" proto "tcp" dport "80" dst "192.168.1.40" dnat4 to "10.10.2.10" inface "eth1" proto "tcp" dport "443" dst "192.168.1.40" # Interfaces #---------------- interface "eth1" "main" policy deny protection bad-packets client icmp accept server4 ping accept with hashlimit ping upto 1/s burst 2 # cfauth: server4 "cfssh" accept src "192.168.0.0/16" # cfsystem: client "http" accept uid "root" # cfsystem: client "https" accept uid "root" # cfsystem: client "ntp" accept uid "root ntpd" # cfsystem: client "cfsmtp" accept uid "root Debian-exim" # cfsystem: client "puppet" accept uid "root" # cfnetwork: client "dns" accept interface "eth0" "vagrant" policy deny protection bad-packets client icmp accept server4 ping accept with hashlimit ping upto 1/s burst 2 # cfauth: server4 "cfssh" accept src "10.0.0.0/8 192.168.0.0/16 172.16.0.0/12" # cfsystem: client "http" accept uid "root" # cfsystem: client "https" accept uid "root" # cfsystem: client "ntp" accept uid "root ntpd" # cfsystem: client "cfsmtp" accept uid "root Debian-exim" # cfsystem: client "puppet" accept uid "root" # cfnetwork: client4 "dns" accept dst "10.10.1.10" interface "eth2" "infradmz" policy reject client icmp accept server icmp accept # cfauth: server4 "cfssh" accept src "10.0.0.0/8" # cfsystem: client "http" accept uid "root" # cfsystem: client "https" accept uid "root" # cfsystem: client "ntp" accept uid "root ntpd" # cfsystem: client "cfsmtp" accept uid "root Debian-exim" # cfsystem: client "puppet" accept uid "root" # cfnetwork: client4 "dns" accept dst "10.10.1.10" interface "eth3" "dbdmz" policy reject client icmp accept server icmp accept # cfauth: server4 "cfssh" accept src "10.0.0.0/8" # cfsystem: client "http" accept uid "root" # cfsystem: client "https" accept uid "root" # cfsystem: client "ntp" accept uid "root ntpd" # cfsystem: client "cfsmtp" accept uid "root Debian-exim" # cfsystem: client "puppet" accept uid "root" interface "eth4" "webdmz" policy reject client icmp accept server icmp accept # cfauth: server4 "cfssh" accept src "10.0.0.0/8" # cfsystem: client "http" accept uid "root" # cfsystem: client "https" accept uid "root" # cfsystem: client "ntp" accept uid "root ntpd" # cfsystem: client "cfsmtp" accept uid "root Debian-exim" # cfsystem: client "puppet" accept uid "root" interface "lo" "local" policy reject client icmp accept server icmp accept # cfauth: server4 "cfssh" accept src "10.0.0.0/8 192.168.0.0/16" # cfsystem: client "http" accept uid "root" # cfsystem: client "https" accept uid "root" # cfsystem: client "ntp" accept uid "root ntpd" # cfsystem: server "smtp" accept # cfsystem: client "smtp" accept # cfsystem: client "cfsmtp" accept uid "root Debian-exim" # cfsystem: client "puppet" accept uid "root" # Routers #---------------- router "main_infradmz" inface "eth1" outface "eth2" policy drop client icmp accept # apt: client4 "cfhttp" accept src "10.10.1.10" client4 "ntp" accept src "10.10.1.10" # puppet: client "cfhttp" accept router "main_webdmz" inface "eth1" outface "eth4" policy drop client icmp accept server4 "cfhttp" accept dst "10.10.2.10" router "vagrant_infradmz" inface "eth0" outface "eth2" policy drop client icmp accept server4 "ntp" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "dns" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "aptproxy" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "puppet" accept dst "10.10.1.11" src "10.10.0.0/8" router "infradmz_infradmz" inface "eth2" outface "eth2" policy reject server icmp accept client icmp accept server4 "ntp" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "dns" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "aptproxy" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "puppet" accept dst "10.10.1.11" src "10.10.0.0/8" router "dbdmz_infradmz" inface "eth3" outface "eth2" policy reject server icmp accept client icmp accept server4 "ntp" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "dns" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "aptproxy" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "puppet" accept dst "10.10.1.11" src "10.10.0.0/8" router "webdmz_infradmz" inface "eth4" outface "eth2" policy reject server icmp accept client icmp accept server4 "ntp" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "dns" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "aptproxy" accept dst "10.10.1.10" src "10.10.0.0/8" server4 "puppet" accept dst "10.10.1.11" src "10.10.0.0/8" router "webdmz_dbdmz" inface "eth4" outface "eth3" policy reject server icmp accept client icmp accept server "testdb" accept
ネットワーク構成
モジュール自体はネットワーク設定をその場で変更しようとはしません-これはペンで行うか再起動する必要があります。
# # Generated by cfnetwork::iface puppet module # auto lo iface lo inet loopback source /etc/network/interfaces.d/* # # Generated by cfnetwork::iface puppet module # auto eth3 iface eth3 inet static address 10.10.2.254 netmask 24 up sysctl --ignore net.ipv6.conf.eth3.disable_ipv6=1 # # Generated by cfnetwork::iface puppet module # auto eth2 iface eth2 inet static address 10.10.1.254 netmask 24 up sysctl --ignore net.ipv6.conf.eth2.disable_ipv6=1 # # Generated by cfnetwork::iface puppet module # auto eth1 iface eth1 inet static address 192.168.1.30 netmask 24 gateway 192.168.1.1 dns-nameservers 10.10.1.10 dns-search example.com up ip addr add 192.168.1.40/24 dev eth1 up sysctl --ignore net.ipv6.conf.eth1.disable_ipv6=1 # # Generated by cfnetwork::iface puppet module # auto eth0 iface eth0 inet dhcp netmask 255.255.255.0 up ip route add 10.0.1.1/25 dev eth0 up sysctl --ignore net.ipv6.conf.eth0.disable_ipv6=1 # # Generated by cfnetwork::iface puppet module # auto eth4 iface eth4 inet static address 10.10.2.254 netmask 24 up sysctl --ignore net.ipv6.conf.eth4.disable_ipv6=1
おわりに
ご覧のとおり、ネットワークとフィルターの構成は基本的でクリーンで簡潔であり、最も重要なことは、山のない変更にはマジックナンバーが便利であることです。
戦闘モードには長い歴史はありません。 実行は、深刻な負荷なしに実サーバーのペアと約12の仮想マシンで実行されます。 したがって、ボランティアはシステム群が成長したことに興味があり、管理へのアプローチはまだ調整する時間がないか、完全に満足していません。