Είναι καθημερινή συζήτηση η ασφάλεια των δεδομένων και o διαμοιρασμός των resources στο περιβάλλον μας. Όλοι μας γνωρίζουμε και κάνουμε αρκετά για αυτά καθημερινά και πάντα ζητάμε το κάτι παραπάνω. Αυτό το κάτι παραπάνω δεν είναι ένα αλλά πολλά και ένα από τα πολλά είναι και αυτό που αναλύω στο άρθρο μου αυτό.
Δεν είναι κάτι συνηθισμένο αλλά θεωρώ ότι θα αρέσει σε πολλούς. Είναι ένα άρθρο haute couture στον SQL Server.
SQL Server TCP connection
Όλοι κάποια στιγμή έχουμε στήσει ένα SQL Server είτε σωστά είτε λάθος. Αυτό που πάντα κάνουμε είναι να πάμε στο SQL Server Configuration Manager και να κάνουμε enable το TCP και να δημιουργήσουμε το αντίστοιχο firewall rule για να μπορούν οι users να συνδέονται σε αυτόν.
Ξέρουμε ότι το default instance ακούει στην πόρτα 1433 (την οποία φυσικά μπορούμε να την αλλάξουμε) και τα named instances έχουν dynamic port αρχικά που μπορούμε να την αλλάξουμε σε static.
Πόσοι όμως έχουν προσέξει το Listen All property στο Protocol tab του ΤCP/IP Properties dialog;
Και πόσοι έχουν δώσει την πρέπουσα σημασία στο IP Addresses tab του ίδιου dialog;
Για να το εξηγήσουμε λίγο αυτό.
Όταν σε ένα box έχουμε περισσότερες από μια κάρτες δικτύου ή περισσότερες IP Addresses σε μια κάρτα με την προϋπόθεση ότι είναι έγκυρες ο SQL Server εφόσον στο Listen All property έχουμε επιλέξει Yes ακούει σε όλες αυτές και σε όλες αυτές ακούει στo port που έχουμε ορίσει στο IPAll section του IP Addresses tab.
Αν θέλουμε να μην γίνεται αυτό θα πρέπει να επιλέξουμε No στο Listen All property και σε αυτές τις IP Address που θέλουμε να ακούει ο SQL Server στο αντίστοιχο IPx θέτουμε το Enabled σε Yes και φυσικά σε κάθε μία μπορούμε να επιλέξουμε και τo port που θέλουμε η κάθε μια να ακούει.
Εύλογα θα αναρωτηθεί κάποιος γιατί να κάνω κάτι τέτοιο. Αρκετοί είναι οι λόγοι που μπορούν να αναφερθούν ένας από αυτούς είναι η αυξημένη ασφάλεια καθώς έχουμε την δυνατότητα σε συνδυασμό με το firewall configuration να ελέγξουμε καλύτερα ποιοι και πως μπαίνουν στο SQL Server. Ιδιαίτερα όταν έχουμε ένα SQL Server instance που σε αυτό μπαίνουν τόσο εσωτερικοί users (domain/DMZ) αλλά και εξωτερικοί users (internet).
Θα πρέπει επίσης να αναφέρω ότι ακόμα και αν επιθυμώ να μην αλλάξω το Listen All property σε Νο και θέλω το SQL Server instance μου να ακούει σε όλες τις IP Addresses αλλά θέλω για τους εσωτερικούς να έχω άλλo port, για τους εξωτερικούς άλλο port, για το IT Support άλλο port κλπ μπορώ να βάλω περισσότερα από ένα ports στο IPAll του IP Address tab (comma separated)
TDS Endpoint
Σε κάθε περίπτωση είτε θέλω ξεχωριστές IP Address και ports είτε όλες τις IP Address αλλά πολλά port θα πρέπει για κάθε port να έχω δημιουργήσει τα αντίστοιχα endpoints και να δώσω connect permission στους users που θέλω να χρησιμοποιήσουν αυτά. Αυτό μπορώ να το κάνω με την CREATE ENDPOINT FOR SQL.
Αν για παράδειγμα θέλω όλες οι IP Addresses να ακούνε σε ακόμα ένα port πχ το 50231 θα πρέπει να δημιουργήσω το αντίστοιχο endpoint ως εξής:
CREATE ENDPOINT [TSQL50231]
STATE = STARTED
AS TCP
(LISTENER_PORT = 50231, LISTENER_IP =ALL)
FOR TSQL() ;
GO
Αν θέλω το συγκεκριμένο port να δεθεί με συγκεκριμένη IP Address (πχ 10.10.10.10) τότε θα πρέπει να δημιουργηθεί ως εξής:
CREATE ENDPOINT [TSQL50231]
STATE = STARTED
AS TCP
(LISTENER_PORT = 50231, LISTENER_IP =10.10.10.10)
FOR TSQL() ;
GO
Για να δώσω permissions σε κάποιον user (πχ user1) σε αυτό το endpoint θα πρέπει να το κάνω με το εξής:
GRANT CONNECT ON ENDPOINT::[TSQL50231] to [user1] ;
GO
Τι θα κάνει αυτό;
Όπως είναι γνωστό όλοι οι users είναι μέλη του public role ο οποίος έχει ένα και μοναδικό permission το connect στο default endpoint. Όταν όμως φτιάχνω ένα νέο TSQL Endpoint αυτό γίνεται revoke από το public role και μόνο όσοι είναι sysadmins στον SQL Server μπορούν να το χρησιμοποιήσουν και με αυτό δίνω connect permissions στο συγκεκριμένο user. Εφόσον συγκεκριμένος χρήστης όπως είπα και πριν δεν είναι sysadmin αν προσπαθήσει να συνδεθεί με τα defaults δεν θα μπορέσει όπως φαίνεται παρακάτω.
Αν όμως πραγματοποιήσει αυτό με το port του endpoint τότε θα είναι επιτυχής η σύνδεση.
Μπορώ να το επιβεβαιώσω αυτό αν γράψω το παρακάτω DMV query
Mapping Connection to NUMA
Έχοντας υλοποιήσει όλα τα παραπάνω και εφόσον είμαι σε ένα box που υποστηρίζει και έχει NUMA μπορώ να δρομολογήσω το κάθε endpoint να χρησιμοποιεί συγκεκριμένο(α) NUMA(s). To αν στο box μου έχω NUMA (μην το δείτε από τον task manager διότι μπορεί να έχει δημιουργεί soft NUMA) μπορώ να το δω είτε από τα SQL Server logs είτε με το παρακάτω query
Αν έχω κάτι τέτοιο τότε μπορώ στο κάθε endpoint να ελέγξω πόσα NUMA θα χρησιμοποιεί που στην ουσία σημαίνει και πόσα cores θα χρησιμοποιεί (όσα είναι το σύνολο των cores που τα κάθε NUMA έχει).
Για να γίνει αυτό θα πρέπει να βάλω δίπλα στο port μέσα σε [ ] το binary representation των NUMA nodes που θέλω σε decimal ή hex format.
Αυτό γίνεται ως εξής
Ένα byte είναι 8 bits το οποίο γεμίζω με μηδέν 00000000. Το πρώτο δεξί bit συμβολίζει το πρώτο NUMA node το δεύτερο δεξί bit το δεύτερο NUMA node κλπ.
Αν θέλω το συγκεκριμένο endpoint να χρησιμοποιεί το πρώτο, το τρίτο και το πέμπτο NUMA node κάνω τα bit αυτά ένα (1) και έτσι έχω το binary 00010101 το decimal αυτού είναι το είκοσι ένα (21) και το hex είναι το (0x15)
Έτσι δίπλα στο port number βάζω σε [ ] το binary δηλαδή 50231[21] ή 50231[0x15].
Με αυτό πετυχαίνω αν ένα port έχει πάρει περισσότερα NUMA nodes o SQL Server να κάνει round-robin σε αυτά για κάθε connection που γίνεται σε αυτό το port. Προσοχή δεν μιλάω για balancing across nodes. Αυτό όπως γίνεται εύκολα κατανοητό μπορώ να έχω επιμερισμό στους πόρους που το κάθε connection έχει.
//antonch