Pokazywanie postów oznaczonych etykietą RHCE. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą RHCE. Pokaż wszystkie posty

[RH7] Tworzenie targetu iSCSI - targetcli

Red Hat 7.x / CentOS 7.x
Zarządzanie targetami iSCSI w wersji 7 odbywa się poprzez narzędzie targetcli. Narzędzie jest rozbudowane i możemy przy jego pomocy zarządzać kilkoma rodzajami storage'u onlineowego (o innych rodzajach może w przyszłości).

Realizację zadania rozpoczniemy oczywiście od instalacji i uruchomienia pakietu targetcli. Ważne, aby pamiętać o systemctl enable - bez tego konfiguracja targetów nie będzie ładowana po restarcie systemu:

[root@server ~]# yum install targetcli
[root@server ~]# systemctl enable target
Created symlink from /etc/systemd/system/multi-user.target.wants/target.service to /usr/lib/systemd/system/target.service.
[root@server ~]# systemctl start target

Narzędzie udostępnia nam swoistą powłokę, w ramach której operujemy na naszych udziałach dyskowych. Wywołanie go daje taki oto efekt:

[root@server ~]# targetcli
targetcli shell version 2.1.fb41
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/>

Na pierwszy rzut oka powłaka wydaje się być dziwna, ale z jej poziomu możemy wywołać helpa - i tu niespodzianka, help jest ciekawie zorganizowany - zależnie od poziomu drzewa help wyświetla opcje specyficzne dla tej właśnie lokalizacji.
Powłoka przedstawia nam w formie hierarchicznej konfigurację storage'ów możliwych do skonfigurowania. Część z nich jest dostępna jedynie, w przypadku kiedy wspierający rozwiązanie hardware jest obecny w naszym systemie. Inne znich są dostępne zawsze.
Poruszanie się po drzewie odbywa się analogicznie do poruszania w systemie - ls i cd.

[root@server ~]# targetcli
targetcli shell version 2.1.fb41
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/> ls
o- / ..................................................................... [...]
  o- backstores .......................................................... [...]
  | o- block .............................................. [Storage Objects: 0]
  | o- fileio ............................................. [Storage Objects: 0]
  | o- pscsi .............................................. [Storage Objects: 0]
  | o- ramdisk ............................................ [Storage Objects: 0]
  o- iscsi ........................................................ [Targets: 0]
  o- loopback ..................................................... [Targets: 0]
/> cd iscsi
/iscsi> ls
o- iscsi .......................................................... [Targets: 0]
/iscsi>

Backstores

Udostępnianie powierzchni dyskowej dobrze jest rozpocząć od zdefiniowania tego, co i w jakiej ilości chcemy udostępniać. Obiekty takie - zwane backstores możemy zdefiniować w oparciu o cztery komponenty:
- block - to udostępnienie zwykłego urządzenia blokowego, które możemy znaleźć w katalogu /sys/block (np. /dev/sdb)
- fileio - to przestrzeń, którą zaalokujemy w pliku na naszym filesystemie (file I-O)
- pscsi - to urządznie typu pass-through SCSI, czyli np. dysk SAS-owy
- ramdisk - emulujące protokół SCSI na obszarze zarezerwowanym w pamięci RAM.

Tworzenie na podstawie każdego z typów rozpoczyna się identycznie - od przejścia do odpowiedniego "katalogu" w drzewie konsoli, czyli np. jeśli chcemy udostępnić powierzchnię 1GB, która fizycznie będzie się znajdować w pliku na naszym lokalnym dysku, skorzystamy z backstore'a typu fileio:

/> cd backstores/fileio
/backstores/fileio>

Wszystkie opcje dostępne w tej lokalizacji możemy podejrzeć poprzez polecenie help, a detale komendy poprzez help POLECENIE.
Jak łatwo wydedukować na podstawie takiego helpa, tworzenie backstore'a zrealizujemy poleceniem create, który jako parametrów potrzebuje nazwy i lokalizacji pliku, w którym zostanie zaalokowany.

Niestety help zawiera pewną nieścisłość - zaznaczono tam parametr size jako opcjonalny, co może zostać źle zrozumiane. Jego opcjonalność polega bowiem na fakcie, że jest opcjonalny jedynie dla komendy create, przy czym jeśli create tworzyć ma backstore typu fileio, jest on wymagany, a jeśli tyczy się typu block należy go pominąć.

Opcjonalnymi parametrami komendy są:
- write_back - przyjmujący parametr true (domyślnie) jeśli chcemy korzystać z cache lokalnego filesystemu, lub false, jeśli chcemy operować w trybie write_thru. Tryb z włączonym write_back zwiększa co prawda wydajność, ale i możliwość utraty danych, które nie są zapisywane bezpośrednio na dysku.
- sparse - to opcja używana jedynie w przypadku tworzenia nowych plików dla typu fileio - jeśli ustawiona jest na true (domyślnie) fizyczna zajętość dysku będzie rosła wraz z ilością danych w pliku - wartość false zajmie zadeklarowaną powierzchnię na naszym filesystemie od razu. Efekt użycia może zaskoczyć - zmieścimy 20G plik sparse na dysku o pojemności 1G... oczywiście do czasu wykorzystania 1G w udostępnionym później iSCSI.

Stwórzmy zatem nasz backstore:

/backstores/fileio> create my_file_backstore /opt/my_file_backstore 1G write_back=false
Created fileio my_file_backstore with size 1073741824
/backstores/fileio> ls
o- fileio ........................................................... [Storage Objects: 1]
  o- my_file_backstore .......... [/opt/my_file_backstore (1.0GiB) write-thru deactivated]
/backstores/fileio> cd ../..
/> ls
o- / ............................................................................... [...]
  o- backstores .................................................................... [...]
  | o- block ........................................................ [Storage Objects: 0]
  | o- fileio ....................................................... [Storage Objects: 1]
  | | o- my_file_backstore ...... [/opt/my_file_backstore (1.0GiB) write-thru deactivated]
  | o- pscsi ........................................................ [Storage Objects: 0]
  | o- ramdisk ...................................................... [Storage Objects: 0]
  o- iscsi .................................................................. [Targets: 1]
  | o- iqn.2003-01.org.linux-iscsi.server.x8664:sn.ca677b0f8d08 ................ [TPGs: 1]
  |   o- tpg1 ..................................................... [no-gen-acls, no-auth]
  |     o- acls ................................................................ [ACLs: 0]
  |     o- luns ................................................................ [LUNs: 0]
  |     o- portals .......................................................... [Portals: 1]
  |       o- 0.0.0.0:3260 ........................................................... [OK]
  o- loopback ............................................................... [Targets: 0]
/>

Target

Target iSCSI możemy chyba z grubsza opisać jako nazwany obiekt, który dla zdefiniowanych odbiorców zewnętrznych (ip, acl) będzie udostępniał zasoby wewnętrzne serwera (backstore).
 
Tworzenie targetu iSCSI możemy zrealizować w 2 wariantach - z domyślną lub zdefiniowaną nazwą.
Pierwsza opcja polega po prostu na wydaniu wewnątrz "katalogu" iscsi polecenia:

/iscsi> create
Created target iqn.2003-01.org.linux-iscsi.server.x8664:sn.ca677b0f8d08.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.

/iscsi> ls
o- iscsi .......................................................... [Targets: 1]
  o- iqn.2003-01.org.linux-iscsi.server.x8664:sn.ca677b0f8d08 ........ [TPGs: 1]
    o- tpg1 ............................................. [no-gen-acls, no-auth]
      o- acls ........................................................ [ACLs: 0]
      o- luns ........................................................ [LUNs: 0]
      o- portals .................................................. [Portals: 1]
        o- 0.0.0.0:3260 ................................................... [OK]
/iscsi>

Stworzenie targetu ze zdefiniowaną nazwą wygląda identycznie, z tym, że po poleceniu create podajemy ową nazwę, np: create iqn.2016-03.server:moj.storage.
Definiowana przez nas nazwa musi być kwalifikowana jako IQN, NAA lub EUI.

TPG oraz iSCSI Portal

TPG, czyli Target Portal Groups pozwalają iSCSI korzystać w wielu konfiguracji w ramach jednego targetu. Jedna grupa TPG jest tworzona domyślnie przy kreowaniu targetu, i w większości przypadków będzie wystarczająca.

W ramach grupy TPG definiowane są tzw. portale, które definiują adres ip oraz port poprzez które target może zostać użyty. Domyślnie w ramach każdego TPG tworzony jest portal domyślny, udostępniający target poprzez wszystkie skonfigurowane adresy IP z użyciem portu 3260.
W przypadku, kiedy chcemy ograniczyć dostępność naszego targetu do jednego adresu skonfigurowanego na maszynie możemy utworzyć taki portal poprzez polecenie create 192.168.1.1 6290 wydane w lokalizacji iscsi/<idn_target>/tpg1/portals/.

LUN-y

Kiedy już wiemy gdzie będziemy udostępniać, przyszła kolej na skonfigurowanie co będziemy udostępniać, poprzez dowiązanie wcześniej  ustawianych backstore'ów do naszego targetu.
Analogicznie do poprzednich kroków, konfiguracji dokonywać będziemy w "katalogu" z nazwą odpowiadającą zagadnieniu, a więc luns w lokalizacji odpowiadającej naszemu targetowi, czyli iscsi/<idn_target>/tpg1/.

Dowiązanienie backstore'a do targetu polega na wskazaniu go jako parametru polecenia create:

/iscsi/iqn.20...d08/tpg1/luns> create /backstores/fileio/my_file_backstore
Created LUN 0.

Szybkie sprawdzenie, czy lun się dowiązał:

/iscsi/iqn.20...d08/tpg1/luns> ls /
o- / ........................................................................................................ [...]
  o- backstores ............................................................................................. [...]
  | o- block ................................................................................. [Storage Objects: 0]
  | o- fileio ................................................................................ [Storage Objects: 1]
  | | o- my_file_backstore ................................. [/opt/my_file_backstore (1.0GiB) write-thru activated]
  | o- pscsi ................................................................................. [Storage Objects: 0]
  | o- ramdisk ............................................................................... [Storage Objects: 0]
  o- iscsi ........................................................................................... [Targets: 1]
  | o- iqn.2003-01.org.linux-iscsi.server.x8664:sn.ca677b0f8d08 ......................................... [TPGs: 1]
  |   o- tpg1 .............................................................................. [no-gen-acls, no-auth]
  |     o- acls ......................................................................................... [ACLs: 0]
  |     o- luns ......................................................................................... [LUNs: 1]
  |     | o- lun0 ............................................. [fileio/my_file_backstore (/opt/my_file_backstore)]
  |     o- portals ................................................................................... [Portals: 1]
  |       o- 0.0.0.0:3260 .................................................................................... [OK]
  o- loopback ........................................................................................ [Targets: 0]

ACLe

Mamy co udostępnić, mamy adres pod którym będzie się to działo, powinniśmy teraz zadbać o to komu będziemy udostępniać.
Każdy klient, łączący się do naszego zasobu iSCSI posiadać powinien unikalną nazwę inicjatora. Nazwa ta może być znalezniona w pliku /etc/iscsi/initiatorname.iscsi na maszynie klienta, a jej znajomość umożliwi nam konfigurację Access Control List dla danego zasobu.

[root@iscsi-client ~]# cat /etc/iscsi/initiatorname.iscsi
InitiatorName=iqn.1994-05.com.redhat:ccfb1428b2a

Znając tą nazwę, możemy utworzyć odpowiedni wpis na naszej liście kontroli dostępu.

/iscsi/iqn.20...d08/tpg1/luns> cd ../acls
/iscsi/iqn.20...d08/tpg1/acls> create iqn.1994-05.com.redhat:ccfb1428b2a
Created Node ACL for iqn.1994-05.com.redhat:ccfb1428b2a
Created mapped LUN 0.

/iscsi/iqn.20...d08/tpg1/acls> ls
o- acls ................................................................................................. [ACLs: 1]
  o- iqn.1994-05.com.redhat:ccfb1428b2a .......................................................... [Mapped LUNs: 1]
    o- mapped_lun0 ........................................................... [lun0 fileio/my_file_backstore (rw)]

Usuwanie definicji

Nie było sensu pisać tego przy każdej pozycji, ponieważ usuwanie elementów konfiguracji w konsoli targetcli zawsze wygląda tak samo.
1. Nawigujemy do lokalizacji odpowiadającej kategorii elementu, który chcemy usunąć
2. Wydajemy polecenie delete nazwa_elementu_do_usuniecia (p.s. działa tabulator)

[RH7] Konfiguracja i edycja reguł lokalnego firewalla [PT.2 - port rules, masquerading, direct rules, lockdown]

Red Hat 7.x / CentOS 7.x
W pierwszej części było kilka słów teoretycznych i podstawowa konfiguracja firewalld - zony i serwisy. Czas brnąć dalej.

Konfiguracja otwarcia portów

Poza definiowalnymi serwisami pozostaje nam oczywiście możliwość dodawania customowych reguł filtrowania opartych o zwyczajowe numery portów, z jakich chcemy ruch do naszego systemu wpuszczać.
Jak można się domyślać po dwóch poprzednich zagadnieniach, definicja będzie opierać się na podaniu strefy, w której regułe chcemy umieścić, oraz numeru portu - wrażenie jest jak najbardziej prawidłowe, ponieważ wszystkie definicje zostały w firewalld zunifikowane.
Rozpocznijmy od listowania definicji portów, jakie mamy już zdefiniowane w naszych strefach:

[root@server ~]# firewall-cmd --list-ports

Listowanie takie dotyczy, tak jak wcześniej domyślnej strefy (listowanie innej wymaga użycia przełącznika --zone=nazwa_strefy).
Nie uzyskaliśmy żadnej odpowiedzi, co oznacza, że strefa nie zawiera definicji dla portów - ale samo przejście komendy bez echa może być nieco dezorientujące.
I tutaj muszę przypomnieć wcześniejsze Post Scriptum, mianowicie przełącznik --list-ports, tak jak wspominany tam --list-services pokazuje nam jedno, konkretne zagadnienie konfiguracyjne, bez wglądu w inne parametry. Moim zdaniem zapytanie idealnie nadaje się do skryptowania opartego o te reguły, ale w codziennej administracji bardziej przejrzyste jest --list-all.
Krótki rzut oka na pełną konfigurację - dla sprawdzenia reguł portów usunąłem wszystkie serwisy z poprzedniej konfiguracji:

[root@server ~]# firewall-cmd --list-all
dmz (default, active)
  interfaces: enp0s3 enp0s9
  sources:
  services:
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

Tutaj widać wyraźnie - nie ma żadnych definicji portów. Brak serwisu ssh oznacza, że nie mamy otwartego portu 22, i próba połączenia potwierdza to. Zdefiniujmy zatem, dla porównania, otwarcie ruchu do ssh nie używając serwisów:

[root@server ~]# firewall-cmd --add-port=22/tcp
success
[root@server ~]# firewall-cmd --list-all
dmz (default, active)
  interfaces: enp0s3 enp0s8
  sources:
  services:
  ports: 22/tcp
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

Tak jak w poprzednich elementach konfiguracji, usunięcie portu zrealizujemy poprzez przełącznik --remove-port.
Przydatna również może okazać się możliwość otwarcia zakresu portów, np:

[root@server ~]# firewall-cmd --add-port=20-23/tcp
success
[root@server ~]# firewall-cmd --list-all
dmz (default, active)
  interfaces: enp0s3 enp0s8 enp0s9
  sources:
  services:
  ports: 20-23/tcp
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

Tym sposobem możemy otwierać ruch na dowolnym porcie i protokole, zależnie od potrzeby.

Masquerade - port forwarding

Konfiguracja forwardowania portów ma analogiczną składnię, przy czym ilość parametrów, z oczywistych względów jest większa.
Aby forwardowanie miało szansę zadziałać, w pierwszej kolejności wymagane jest uruchomienie usługi masqueradingu:

[root@server ~]# firewall-cmd --add-masquerade
success

Obecny status jest doskonale widoczny w widoku generowanym przez przełącznik --list-all.
Samo przekierowanie portu możemy realizować zarówno na określony port jak i adres ip, lub uwzględniając oba elementy jednocześnie. Składnia przełącznika nie wygląda może zbyt przyjaźnie, ale jest bardzo logicznie uporządkowana - zawiera sekcje port (port na który przychodzi ruch), proto (protokół komunikacji), topotr (docelowy port przekierowania) oraz toaddr (docelowy adres przekierowania):

[root@server ~]# firewall-cmd --add-forward-port=port=50:proto=tcp:toport=22
success
[root@server ~]# firewall-cmd --list-all
dmz (default, active)
  interfaces: enp0s3 enp0s8
  sources:
  services:
  ports:
  masquerade: yes
  forward-ports: port=50:proto=tcp:toport=22:toaddr=
  icmp-blocks:
  rich rules:

W ramach testu działania zamknąłem na maszynie wszystkie porty, otwierając jedynie port 50/TCP - zdefiniowane przekierowanie umożliwiło zalogowanie się ssh na maszynę poprzez port 50 - a odrzuciło połączenie po standardowym 22, więc rezultat jest zgodny z oczekiwaniami.

Dodawanie reguł direct i chain-ów

firewall-cmd pozostawia nam możliwość operowania ra regułach analogicznych do tych, które pamiętamy z iptables. Reguły te są wpisywane bezpośrednio do tablic iptables, a korzystanie z nich wymaga  zrozumienia konstrukcji łańcuchów iptables.
Składnia tego typu definicji wygląda następująco:

[root@server ~]# firewall-cmd [--permanent] --direct --add-rule {ipv4|ipv6|eb} table chain priority args

Przełącznik --permanent odpowiada oczywiście za trwałe zapisanie reguły w systemie. --add-rule jak sugeruje nazwa odpowiada za dodanie reguły. Reguła taka musi mieć określony protokół (ipv4, ipv6 lub ethernet bridges). Kolejnymi elementami wymaganymi są tablica iptables do której reguła ma być dodana oraz odpowiedni chain.
Priorytet wykorzystywany jest do zarządzania kolejnością reguł - 0 oznacza dodanie reguły na początku tablicy, a kolejne numery powodują dodanie jej odpowiednio dalej. Dodanie kilku reguł z jednakowym priorytetem może spowodować przypadkową kolejność ich stosowania (w ramach priorytetu), dlatego, jeśli zależy nam na wymuszeniu kolejności warto zastosować różne priorytety.
Argumentami komendy będą przełączniki stosowane w iptables.
Przykładowe polecenie może wyglądać następująco:

[root@server ~]# firewall-cmd --direct --add-rule ipv4 filter IN_dmz_allow 0 -m tcp -p tcp --dport 2345 -j ACCEPT

Zdefiniowane wcześniej reguły możemy przeglądać poleceniem:

[root@server firewalld]# firewall-cmd --direct --get-all-rules
ipv4 filter IN_dmz_allow 0 -m tcp -p tcp --dport 2345 -j ACCEPT

lub dla konkretnej tablicy:

[root@server firewalld]# firewall-cmd --direct --get-rules ipv4 filter IN_dmz_allow
0 -m tcp -p tcp --dport 2345 -j ACCEPT

Przełącznik --direct umozliwia nam również definiowanie własnych chain-ów w odpowiednich tablicach.

[root@server firewalld]# firewall-cmd --direct --add-chain ipv4 filter test_chain
success

A zdefiniowane przez nas chain-y możemy podejrzeć przez:

[root@server firewalld]# firewall-cmd --direct --get-all-chains
ipv4 filter test_chain

Usuwanie, zarówno reguł jak i chain-ów realizujemy analogicznie, używając odpowiednio przełączników --remove-rule i --remove-chain.

Cały czas pozostaje nam możliwość weryfikowania zdefiniowanych reguł poprzez klasyczne iptables -nL, ale ilość tablic powoduje, że nie są one zbyt czytelne.

Lockdown - blokowanie możliwości zmian reguł przez aplikacje

Aplikacje oraz serwisy, jeśli są uruchomione z uprawnieniami root, mają możliwość zmiany konfiguracji firewalla (np. libvirt). Opcja lockdown daje nam możliwość kontrolowania tych możliwości.
Lockdown konfiguracji wykonujemy poprzez ustawienie wartości yes w pliku /etc/firewalld/firewalld.conf

[root@server firewalld]# vi /etc/firewalld/firewalld.conf
[...]
Lockdown=yes
[...]
[root@server firewalld]# firewall-cmd --reload
success
[root@server firewalld]# firewall-cmd --query-lockdown
yes

Po przeładowaniu, zmian w konfiguracji będą mogły dokonywać jedynie aplikacje zdefiniowane na białej liście, w pliku /etc/firewalld/lockdown-whitelist.xml
Plik posiada predefiniowane reguły, które umożliwiają edycję reguł np. root-owi - do przetestowania działania usunąłem je z pliku - efekt jest zgodny ze spodziewanym:

[root@server firewalld]# firewall-cmd --add-service ftp
Error: ACCESS_DENIED: lockdown is enabled

Lockdown, a w zasadzie reguły whitelist mogą być zdefiniowane w oparciu o kilka elementów:
- context - konteksty selinuxowe danej aplikacji (ps -e --context)
- uid - id użytkownika
- user - nazwa użytkownika
- commands - polecenia
i w takiej też kolejności są przez lockdown sprawdzane.

Zarządzanie odbywa się przez przełączniki:

[root@server firewalld]# firewall-cmd --add-lockdown-whitelist-command='/usr/bin/python -Es /usr/bin/firewall-cmd'
success
[root@server firewalld]# firewall-cmd --add-lockdown-whitelist-context='system_u:system_r:kernel_t:s0'
success
[root@server firewalld]# firewall-cmd --add-lockdown-whitelist-uid=500
success
[root@server firewalld]# firewall-cmd --add-lockdown-whitelist-user=test
success

Usuwać reguły będziemy identycznie, zastępując --add-lockdown-... przez --remove-lockdown...

Weryfikacja odbywać się może poprzez:

[root@server firewalld]# firewall-cmd --list-lockdown-whitelist-user
test
[root@server firewalld]# firewall-cmd --list-lockdown-whitelist-uid
500
[root@server firewalld]# firewall-cmd --list-lockdown-whitelist-context
system_u:system_r:kernel_t:s0
[root@server firewalld]# firewall-cmd --list-lockdown-whitelist-command
/usr/bin/python -Es /usr/bin/firewall-cmd

Konfiguracja i edycja reguł lokalnego firewalla - firewalld i firewall-cmd [PT.1 - zones & services]