Πώς ExpressVPN διατηρεί τους διακομιστές ιστού patched και ασφαλή

[ware_item id=33][/ware_item]

Ο διακομιστής ExpressVPN ανεβαίνει από τις στάχτες.


Αυτό το άρθρο εξηγεί την προσέγγιση του ExpressVPN διαχείριση της ενημερωμένης έκδοσης κώδικα ασφαλείας για την υποδομή που εκτελεί τον ιστότοπο ExpressVPN (όχι οι διακομιστές VPN). Γενικά, η προσέγγισή μας στην ασφάλεια είναι:

  1. Κάνετε τα συστήματα πολύ δύσκολο να χαράξει.
  2. Ελαχιστοποιήστε τις πιθανές ζημιές εάν ένα σύστημα υποθετικά παίρνει hacked και αναγνωρίζουν το γεγονός ότι ορισμένα συστήματα δεν μπορούν να γίνουν απόλυτα ασφαλή. Τυπικά, αυτό αρχίζει στη φάση αρχιτεκτονικού σχεδιασμού, όπου ελαχιστοποιούμε την πρόσβαση μιας εφαρμογής.
  3. Ελαχιστοποιήστε το χρόνο ότι ένα σύστημα μπορεί να παραμείνει σε κίνδυνο.
  4. Επικυρώνω αυτά τα σημεία με τακτικές πέντες, εσωτερικές και εξωτερικές.

Η ασφάλεια είναι ριζωμένη στον πολιτισμό μας και είναι το κύριο μέλημα που καθοδηγεί όλη τη δουλειά μας. Υπάρχουν πολλά άλλα θέματα, όπως οι πρακτικές ανάπτυξης λογισμικού ασφάλειας, η ασφάλεια εφαρμογών, οι διαδικασίες και η κατάρτιση των εργαζομένων κ.λπ., αλλά αυτές δεν εμπίπτουν στο πεδίο εφαρμογής αυτής της δημοσίευσης.

Εδώ εξηγούμε πώς επιτυγχάνουμε τα εξής:

  1. Βεβαιωθείτε ότι όλοι οι διακομιστές είναι πλήρως ενημερωμένοι και όχι περισσότερο από 24 ώρες από τις δημοσιεύσεις των CVE.
  2. Βεβαιωθείτε ότι δεν χρησιμοποιείται ποτέ διακομιστής για περισσότερο από 24 ώρες, τοποθετώντας έτσι ένα ανώτατο όριο στο χρόνο που ένας επιτιθέμενος μπορεί να έχει επιμονή.

Επιτυγχάνουμε και τους δύο στόχους μέσω ενός αυτοματοποιημένο σύστημα που ανοικοδομεί τους διακομιστές, ξεκινώντας από το λειτουργικό σύστημα και όλες τις τελευταίες ενημερώσεις κώδικα και τις καταστρέφει τουλάχιστον μία φορά κάθε 24 ώρες.

Η πρόθεσή μας για αυτό το άρθρο είναι να είναι χρήσιμη για άλλους προγραμματιστές που αντιμετωπίζουν παρόμοιες προκλήσεις και να δώσει διαφάνεια στις δραστηριότητες του ExpressVPN στους πελάτες μας και τα μέσα ενημέρωσης.

Πώς χρησιμοποιούμε τα βιβλία αναπαραγωγής Ansible και Cloudformation

Η υποδομή ιστού του ExpressVPN φιλοξενείται στο AWS (σε αντίθεση με τους διακομιστές VPN που λειτουργούν με αποκλειστικό εξοπλισμό) και αξιοποιούμε τις δυνατότητές του για να καταστήσουμε δυνατή την ανοικοδόμηση.

Ολόκληρη η υποδομή μας διατίθεται με Cloudformation και προσπαθούμε να αυτοματοποιήσουμε όσο το δυνατόν περισσότερες διαδικασίες. Ωστόσο, θεωρούμε ότι η εργασία με τα ακατέργαστα πρότυπα Cloudformation είναι αρκετά δυσάρεστη λόγω της ανάγκης επανάληψης, της γενικής φτωχής αναγνωσιμότητας και των περιορισμών της σύνταξης JSON ή YAML.

Για να μετριάσουμε αυτό, χρησιμοποιούμε ένα DSL που ονομάζεται cloudformation-ruby-dsl που μας επιτρέπει να γράψουμε ορισμούς προτύπων σε πρότυπα Ruby και εξαγωγή Cloudformation σε JSON.

Συγκεκριμένα, το DSL μας επιτρέπει να γράφουμε σενάρια χρηστών ως κανονικά σενάρια τα οποία μετατρέπονται αυτόματα σε JSON (και να μην περάσουν από την οδυνηρή διαδικασία κάνοντας κάθε γραμμή του σεναρίου σε μια έγκυρη συμβολοσειρά JSON).

Ένας γενικός ρόλος Ansible που ονομάζεται cloudformation-infrastructure φροντίζει να μετατρέψει το πραγματικό πρότυπο σε ένα προσωρινό αρχείο, το οποίο στη συνέχεια χρησιμοποιείται από το cloudformation Module:

- όνομα: 'render {{component}} στοίβα cloudformation json'
κέλυφος: ρουμπίνι "{{template_name | προεπιλογή (συστατικό στοιχείο)}}. rb" επέκταση - stack-name {{stack}} - περιοχή {{aws_region}} > {{tempfile_path}} '
args:
chdir: ../cloudformation/templates
changed_when: false

- όνομα: 'δημιουργία / ενημέρωση {{component}} στοίβα'
cloudformation:
stack_name: '{{stack}} - {{xv_env_name}} - {{component}}'
κατάσταση: παρούσα
περιοχή: '{{aws_region}}'
πρότυπο: '{{tempfile_path}}'
template_parameters: '{{template_parameters | Προκαθορισμένο({}) }}'
stack_policy: '{{stack_policy}}'
εγγραφείτε: cf_result

Στο playbook καλούμε το ρόλο της υποδομής cloudformation αρκετές φορές με διαφορετικές μεταβλητές συνιστωσών για να δημιουργήσουμε αρκετές στοίβες Cloudformation. Για παράδειγμα, έχουμε μια στοίβα δικτύου που καθορίζει τον VPC και τους σχετικούς πόρους και μια στοίβα εφαρμογών που ορίζει την ομάδα αυτόματης κλιμάκωσης, τη διαμόρφωση εκκίνησης, τους γάντζους του κύκλου ζωής κλπ..

Στη συνέχεια, χρησιμοποιούμε ένα κάπως άσχημο αλλά χρήσιμο τέχνασμα για να μετατρέψουμε την έξοδο της ενότητας cloudformation σε μεταβλητές Ansible για επόμενους ρόλους. Πρέπει να χρησιμοποιήσουμε αυτήν την προσέγγιση, αφού το Ansible δεν επιτρέπει τη δημιουργία μεταβλητών με δυναμικά ονόματα:

- περιλαμβάνουν: _tempfile.yml
- αντίγραφο:
περιεχόμενο: '{{component} regex_replace ("-", "_")}} _ στοίβα: {{cf_result.stack_outputs | to_json}} '
destination: '{{tempfile_path}}.
no_log: true
changed_when: false

- include_vars: '{{tempfile_path}}.

Ενημέρωση της ομάδας EC2 Auto Scaling

Ο ιστότοπος ExpressVPN φιλοξενείται σε πολλαπλές περιπτώσεις EC2 σε μια ομάδα Auto Scaling πίσω από έναν Balancer Load Application, ο οποίος μας επιτρέπει να καταστρέφουμε τους διακομιστές χωρίς διακοπή, καθώς ο εξισορροπητής φορτίου μπορεί να αποστραγγίσει υπάρχουσες συνδέσεις πριν τερματιστεί η εγκατάσταση.

Η Cloudformation ενορχηστρώνει ολόκληρη την αναδημιουργία και ενεργοποιούμε το αναδυόμενο βιβλίο αναπαραγωγής που περιγράψαμε παραπάνω κάθε 24 ώρες για την αναδημιουργία όλων των παρουσιών, χρησιμοποιώντας το χαρακτηριστικό AutoScalingRollingUpdate UpdatePolicy της AWS :: AutoScaling :: AutoScalingGroup.

Όταν ενεργοποιείται απλώς επανειλημμένα χωρίς αλλαγές, το χαρακτηριστικό UpdatePolicy δεν χρησιμοποιείται - γίνεται μόνο σε ειδικές περιπτώσεις, όπως περιγράφεται στην τεκμηρίωση. Μια από αυτές τις συνθήκες είναι μια ενημέρωση για τη διαμόρφωση εκκίνησης Auto Scaling - ένα πρότυπο που χρησιμοποιεί μια ομάδα Auto Scaling για την εκκίνηση στιγμιότυπων EC2 - το οποίο περιλαμβάνει το σενάριο δεδομένων χρήστη EC2 που εκτελείται κατά τη δημιουργία μιας νέας παρουσίας:

'AppLaunchConfiguration', πληκτρολογήστε: 'AWS :: AutoScaling :: LaunchConfiguration',
Ιδιότητες: {
Όνομα κλειδιού: param ('AppServerKey'),
Εικόνα: param ('AppServerAMI'),
InstanceType: param ('AppServerInstanceType'),
SecurityGroups: [
param ('SecurityGroupApp'),
],
IamInstanceProfile: param ('RebuildIamInstanceProfile'),
Διαδικασία παρακολούθησης: αλήθεια,
BlockDeviceMappings: [
{
DeviceName: '/ dev / sda1', # όγκος ρίζας
Ebs: {
VolumeSize: param ('AppServerStorageSize'),
VolumeType: param ('AppServerStorageType'),
DeleteOnTermination: true,
},
},
],
UserData: base64 (παρεμβολής (αρχείο ('scripts / app_user_data.sh'))),
}}

Αν κάνουμε οποιαδήποτε ενημέρωση στο σενάριο δεδομένων χρήστη, ακόμη και ένα σχόλιο, η διαμόρφωση εκκίνησης θα θεωρηθεί ότι άλλαξε και το Cloudformation θα ενημερώσει όλες τις παρουσίες στην ομάδα Auto Scaling για να συμμορφωθεί με τη νέα διαμόρφωση εκκίνησης.

Χάρη στο cloudformation-ruby-dsl και στη συνάρτηση χρησιμότητας interpolate, μπορούμε να χρησιμοποιήσουμε τις αναφορές Cloudformation στο script app_user_data.sh:

readonly rebuild_timestamp ="{{param ('RebuildTimestamp')}}"

Αυτή η διαδικασία διασφαλίζει ότι η διαμόρφωση εκκίνησής μας είναι καινούργια κάθε φορά που ενεργοποιείται η αναδημιουργία.

Άγκιστρα κύκλου ζωής

Χρησιμοποιούμε τους γάντζους του κύκλου ζωής Auto Scaling για να βεβαιωθείτε ότι τα στιγμιότυπα μας είναι πλήρως εφοδιασμένα και να περάσετε τους απαιτούμενους υγειονομικούς ελέγχους προτού να πάνε ζωντανά.

Η χρήση των αγκιστριών του κύκλου ζωής μας επιτρέπει να έχουμε τον ίδιο κύκλο ζωής στιγμιότυπου τόσο όταν ενεργοποιούμε την ενημέρωση με Cloudformation όσο και όταν συμβαίνει ένα συμβάν αυτόματης κλιμάκωσης (για παράδειγμα, όταν μια παρουσία αποτύχει σε έλεγχο EC2 και τερματίσει). Δεν χρησιμοποιούμε το σήμα cfn και την πολιτική ενημέρωσης αυτόματης κλιμάκωσης WaitOnResourceSignals επειδή εφαρμόζονται μόνο όταν το Cloudformation ενεργοποιεί μια ενημέρωση.

Όταν μια ομάδα αυτόματης κλιμάκωσης δημιουργεί μια νέα παρουσίαση, ενεργοποιείται ο άγκισος κύκλου ζωής EC2_INSTANCE_LAUNCHING και αυτόματα τοποθετεί την εμφάνιση σε κατάσταση αναμονής: αναμονή.

Μετά την πλήρη διαμόρφωση του στιγμιότυπου, αρχίζει να χτυπά τα τελικά σημεία ελέγχου της υγείας του με την καμπύλη από το σενάριο δεδομένων χρήστη. Μόλις οι υγειονομικοί έλεγχοι αναφέρουν ότι η εφαρμογή είναι υγιής, εκδίδουμε μια ΔΙΑΔΙΚΑΣΙΑ ΣΥΝΕΧΗΣ για αυτόν τον γάντζο του κύκλου ζωής, οπότε η περίπτωση συνδέεται με το εξισορροπητή φορτίου και ξεκινά την υπηρεσία.

Εάν οι έλεγχοι υγείας αποτύχουν, εκδίδουμε μια ενέργεια ABANDON η οποία τερματίζει την ελαττωματική παρουσία και η ομάδα αυτόματης κλιμάκωσης εκκινεί μια άλλη.

Εκτός από τη μη επιτυχία των ελέγχων υγείας, το σενάριο δεδομένων χρήστη ενδέχεται να αποτύχει σε άλλα σημεία - για παράδειγμα, εάν τα προσωρινά θέματα σύνδεσης αποτρέπουν την εγκατάσταση του λογισμικού.

Θέλουμε τη δημιουργία μιας νέας υπόθεσης να αποτύχει μόλις καταλάβουμε ότι δεν θα γίνει ποτέ υγιής. Για να το επιτύχουμε, ορίσαμε μια παγίδα ERR στο σενάριο δεδομένων χρήστη μαζί με set -o errtrace για να καλέσουμε μια συνάρτηση που αποστέλλει μια ενέργεια του κύκλου ζωής ABANDON, έτσι ώστε μια ελαττωματική περίπτωση να τερματίσει το συντομότερο δυνατόν.

Σενάρια δεδομένων χρηστών

Το σενάριο δεδομένων χρήστη είναι υπεύθυνο για την εγκατάσταση όλου του απαιτούμενου λογισμικού στην περίπτωση. Χρησιμοποιήσαμε με επιτυχία το Ansible για την παροχή στιγμιότυπων και το Capistrano για την ανάπτυξη εφαρμογών για μεγάλο χρονικό διάστημα, γι 'αυτό και τα χρησιμοποιούμε εδώ, επιτρέποντας την ελάχιστη διαφορά μεταξύ τακτικών εφαρμογών και ανακατασκευών.

Το σενάριο δεδομένων χρηστών ελέγχει το αποθετήριο εφαρμογών μας από το Github, το οποίο περιλαμβάνει δέσμες ενεργειών Provisioning, στη συνέχεια τρέχει το Ansible και το Capistrano υποδεικνύει localhost.

Κατά τον έλεγχο του κώδικα, πρέπει να είμαστε βέβαιοι ότι η τρέχουσα αναπτυσσόμενη έκδοση της εφαρμογής αναπτύσσεται κατά την ανασυγκρότηση. Το σενάριο ανάπτυξης του Capistrano περιλαμβάνει μια εργασία που ενημερώνει ένα αρχείο στο S3 που αποθηκεύει την τρέχουσα υλοποίηση commit SHA. Όταν συμβαίνει η αναδημιουργία, το σύστημα αναλαμβάνει τη δέσμευση που πρόκειται να αναπτυχθεί από αυτό το αρχείο.

Εφαρμόζονται ενημερώσεις λογισμικού τρέχοντας χωρίς επίβλεψη αναβάθμιση στο προσκήνιο με την εντολή unsattended-upgrade -d. Μόλις ολοκληρωθεί, το δείγμα επανεκκινεί και ξεκινά τους ελέγχους υγείας.

Αντιμετώπιση των μυστικών

Ο διακομιστής χρειάζεται προσωρινή πρόσβαση σε μυστικά (όπως τον κωδικό πρόσβασης για την άνοση θύρα) που λαμβάνεται από το κατάστημα παραμέτρων EC2. Ο διακομιστής μπορεί να έχει πρόσβαση μόνο σε μυστικά για σύντομη διάρκεια κατά τη διάρκεια της αναδημιουργίας. Αφού εξαχθούν, αντικαταστήσουμε άμεσα το προφίλ αρχικού στιγμιότυπου με ένα άλλο που έχει μόνο πρόσβαση σε πόρους που απαιτούνται για την εκτέλεση της εφαρμογής.

Θέλουμε να αποφύγουμε την αποθήκευση οποιωνδήποτε μυστικών στη μόνιμη μνήμη του στιγμιότυπου. Το μόνο μυστικό που αποθηκεύουμε στο δίσκο είναι το κλειδί SSH του Github, αλλά όχι η δική του φράση πρόσβασης. Επίσης, δεν αποθηκεύουμε τον κωδικό της Άνοιας θύελλας.

Ωστόσο, πρέπει να περάσουμε αυτές τις φράσεις πρόσβασης σε SSH και Ansible αντίστοιχα και είναι δυνατή μόνο σε διαδραστικό τρόπο (δηλ. Το βοηθητικό πρόγραμμα ζητά από τον χρήστη να εισαγάγει τις φράσεις πρόσβασης με μη αυτόματο τρόπο) για ένα καλό λόγο - εάν μια φράση πρόσβασης είναι μέρος μιας εντολής είναι αποθηκεύονται στο ιστορικό του κελύφους και μπορούν να είναι ορατά σε όλους τους χρήστες του συστήματος εάν εκτελούν ps. Χρησιμοποιούμε το αναμενόμενο βοηθητικό πρόγραμμα για να αυτοματοποιήσουμε την αλληλεπίδραση με αυτά τα εργαλεία:

αναμένω << EOF
cd $ {repo_dir}
spawn κάνει ansible_local env = $ {deploy_env} stack = $ {stack} hostname = $ {server_hostname}
set timeout 2
περιμένετε 'κωδικός Vault'
στείλετε "$ {vault_password} \ r"
set timeout 900
αναμένω {
"απρόσιτο = 0 απέτυχε = 0" {
έξοδος 0
}}
eof {
έξοδος 1
}}
τέλος χρόνου {
έξοδος 1
}}
}}
EOF

Προκάλεσε την ανοικοδόμηση

Δεδομένου ότι ενεργοποιούμε την αναδημιουργία εκτελώντας το ίδιο σενάριο Cloudformation που χρησιμοποιείται για τη δημιουργία / ενημέρωση της υποδομής μας, πρέπει να διασφαλίσουμε ότι δεν ενημερώσουμε τυχαία κάποιο μέρος της υποδομής που δεν πρέπει να ενημερωθεί κατά την αναδημιουργία.

Αυτό επιτυγχάνεται θέτοντας μια πολιτική περιοριστικής στοίβας στις στοίβες Cloudformation, ώστε να ενημερώνονται μόνο οι πόροι που είναι απαραίτητοι για την ανακατασκευή:

{
"Δήλωση" : [
{
"Αποτέλεσμα" : "Επιτρέπω",
"Δράση" : "Ενημέρωση: Τροποποίηση",
"ΔΙΕΥΘΥΝΤΡΙΑ σχολειου": "*",
"Πόρος" : [
"LogicalResourceId / * AutoScalingGroup"
]
},
{
"Αποτέλεσμα" : "Επιτρέπω",
"Δράση" : "Ενημέρωση: Αντικατάσταση",
"ΔΙΕΥΘΥΝΤΡΙΑ σχολειου": "*",
"Πόρος" : [
"LogicalResourceId / * LaunchConfiguration"
]
}}
]
}}

Όταν πρέπει να κάνουμε πραγματικές ενημερώσεις για την υποδομή, πρέπει να ενημερώσουμε με μη αυτόματο τρόπο την πολιτική στοίβας για να επιτρέψουμε ρητά την ενημέρωση αυτών των πόρων.

Επειδή τα ονόματα κεντρικών υπολογιστών και IP των διακομιστών μας αλλάζουν καθημερινά, έχουμε ένα σενάριο που ενημερώνει τις τοπικές αναφορές αποθέματος και τις παραμέτρους SSH. Ανακαλύπτει τις περιπτώσεις μέσω του API AWS με ετικέτες, μετατρέπει τα αρχεία απογραφής και config από τα πρότυπα ERB και προσθέτει τα νέα IP σε SSH known_hosts.

Το ExpressVPN ακολουθεί τα υψηλότερα πρότυπα ασφαλείας

Οι διακομιστές ανοικοδόμησης μας προστατεύουν από μια συγκεκριμένη απειλή: οι επιτιθέμενοι αποκτούν πρόσβαση στους διακομιστές μας μέσω ευπάθειας πυρήνα / λογισμικού.

Ωστόσο, αυτός είναι μόνο ένας από τους πολλούς τρόπους με τους οποίους διατηρούμε την υποδομή μας ασφαλή, περιλαμβανομένων, ενδεικτικά, των τακτικών ελέγχων ασφαλείας και καθιστώντας τα κρίσιμα συστήματα απρόσιτα από το διαδίκτυο.

Επιπλέον, διασφαλίζουμε ότι όλοι οι κώδικες και οι εσωτερικές μας διαδικασίες ακολουθούν τα υψηλότερα πρότυπα ασφαλείας.

Πώς ExpressVPN διατηρεί τους διακομιστές ιστού patched και ασφαλή
admin Author
Sorry! The Author has not filled his profile.