Dodanie dodatkowych kontrolerów domeny w FortiGate do profilu LDAP, włączenie komunikatów o wygasających hasłach i opcja na odnowienie ich

Niestety, tych opcji aktualnie (w wersji FortiOS 6.4.1 jeszcze nie ma w interfejsie, więc trzeba to zrobić przez CLI. Dla przykładu mój profil i poniżej przykład dodania dodatkowych kontrolerów domeny:

anzena-forti # config user ldap
anzena-forti (ldap) # edit serba.local
anzena-forti (serba.local) # set secondary-server dc2.serba.local
anzena-forti (serba.local) # set tertiary-server dc3.serba.local
anzena-forti (serba.local) # set password-expiry-warning enable
anzena-forti (serba.local) # set password-renewal enable
anzena-forti (serba.local) # end

Zmiana nazwy certyfikatu CA w FortiGate

Dzięki temu certyfikat nie jest nazwany domyślnie tak jak na górze, lecz tak jak ten na dole:

anzena-forti # config vpn certificate ca
anzena-forti (ca) # rename CA_CERT_2 to SERBA-CA
table name 'CA_CERT_2' is not found!
Command fail. Return code 2 //jak widać wielkość liter ma znaczenie!
anzena-forti (ca) # rename CA_Cert_2 to SERBA-CA
anzena-forti (ca) # end

Wake on LAN na FortiGate i Mikrotiku

Rachunki za prąd mi nieźle podskoczyły, więc od niedawna włączam kompa tylko wtedy, jeśli go potrzebuję. Dlatego wcześniej łączę się do domu po VPNie i korzystam z opcji Wake on LAN – dzięki czemu mogę zdalnie włączyć komputer, bo niestety on nie ma interfejsu IPMI, ani nie ma w domu drugiej osoby, która mi ten przycisk wciśnie.

FortiGate:

execute wake-on-lan lan 00:d8:61:04:20:69

gdzie lan to nazwa intefejsu, do którego jest podpięty mój komputer, a następnie jest adres MAC mojej karty sieciowej w komputerze.

Mikrotik:

tool wol interface=ether4 mac=00:d8:61:04:20:69

Tutaj tak samo jak wyżej, jedynie nieco inne polecenie.

Certyfikat w agencie FSSO dla FortiGate

Zawsze jak uczę się czegoś (na przykład w pracy) staram się wyciągnąć z tego 100%. Przez to natrafiłem na 1 opcję w agencie FSSO FortiGate’a, której nigdzie nikt nie używa: FortiGate SSL. Nie trudno się domyślić, że tu chodzi o to, by komunikacja z FortiGate’m była szyfrowana (domyślnie jest przesyłana plaintextem). Więc skoro zabezpieczamy wszystko najlepiej to czemu tego nie zmienić?

Problem w tym, że w dokumentacji FortiGate’a ani w ich Cookbooku tego nie ma. Są inne rzeczy, ale tą funkcjonalność ktoś po prostu pominął i nie ma totalnie nic o jej konfiguracji, więc próbowałem się dowiedzieć na własną rękę jak ją się ustawia.

Na początku należy mieć własne CA. Na przykład ja używam do tego CA, które można postawić w AD (Usługi certyfikatów Active Directory):

Ja zawsze do niego doinstalowuję funkcję Rejestracja w sieci Web dla urzędu certyfikacji. Dzięki temu możemy przez stronkę taki certyfikat sobie podpisać, zakładając, że postawiliśmy sobie takie CA na serwerze dc1.serba.local wystarczy wejść na stronkę http://dc1.serba.local/certsrv (oczywiście da się zmienić na HTTPS) i tam możemy załatwić robotę. Część robię za pomocą OpenSSL, więc warto mieć zainstalowaną windowsową wersję lub korzystać z Windows Subsystem for Linux (korzystam z tego „czegoś” w Windows Store, w praktyce daje mi to możliwość korzystania ze wszystkich (prawie) poleceń z Ubuntu lecz będąc na Windowsie).

Zaczynamy od utworzenia klucza prywatnego:

openssl req -newkey rsa:2048 -keyout local.key
Generating a RSA private key
..........+++++
........+++++
writing new private key to 'local.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:PL
State or Province Name (full name) [Some-State]:SL
Locality Name (eg, city) []:Tychy
Organization Name (eg, company) [Internet Widgits Pty Ltd]:it.supra.tf
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:it.supra.tf
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
-----BEGIN CERTIFICATE REQUEST-----
MIICzDCCAbQCAQAwgYYxCzAJBgNVBAYTAlBMMQswCQYDVQQIDAJTTDEOMAwGA1UE
BwwFVHljaHkxFDASBgNVBAoMC2l0LnN1cHJhLnRmMQswCQYDVQQLDAJJVDEUMBIG
A1UEAwwLaXQuc3VwcmEudGYxITAfBgkqhkiG9w0BCQEWEnJhZG9zbGF3QHNlcmJh
Lm92aDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMNpWo2R6qcUQKCO
3rTL2nBnPa33lS9mtvC+j7HHU2ZNHgSYsm6jVP0t3ARWEGPg4soTI95GBojO4KbA
lUNw8D5tza0rj45C70VeNZkk5n6Y9OsoMyOrOPThZTmfJWdZXfN90rZC2leAdy24
7fTkcJ3jgkgHWgjbsu6kWvCLXgzPY71VfIFufDuUTLGHyD4RIAjT6MjML4SMToFU
vSQ3fwUbe+ayAV/XB0O2PR+zJ7TD1W4MoaJwTklPOb0pT/6sGNmOsxQiyoaqbK3q
nW8x37PKCXthwObpJMnyROXsyYCZqaHiDxtK7jEao4jyhUkzqcJyvHrv0RLwMZzr
OFgzxVECAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA+h+TmOmJuzdcAaeYdZmjs
bL1VJR4ih38/LU+ELjha+380SPA9bvbmHNYcGLtc8Y5aMi00TZoRwZ6HO4ALA11Y
JD0f5bC3c/JulHuBy+5wCMw4JyM8GFz2yrayi1wqXJVDp57kDjrB1GWhX8sG2oh6
yf+Y6wJk9zyO48Aglgg7w/ZtEjnyBID182yUxSNEJuBoOooNmGqCQrvTJZFgnXzJ
NQT1f4KlCZhE8g9bA8dWuIW7aAm2ssck/QI15jyj22zNYk0c5m+kdcDhjss6qjFw
m0LXnHCLWWdnBKqqraTy5G7ZNTDGxl43n74bRCGAJkotkh5RxX+e3BzihyCjg5dH
-----END CERTIFICATE REQUEST-----

Dzięki temu mam wygenerowany taki klucz prywatny w pliku local.key:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIeJPiXvMmk/gCAggA
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECGT+mYCIj3sOBIIEyKw37DJsFB6q
GzhFg4K8z71ffvVeEYJwpH5t6PdH5Scg8dV1yXMbKdEL3ZDzpk0sVnghjAb6Z/YW
dXXTeO8oAQqBCdt6B7a+6cA7+Gp3xHOEQlZKE/ijFkvBPPL4cFP3LQ+yQkfzI0i9
sZuuocF8srxtIuOYPbb6DVJZI0C+xB0/QWQnF4WdyncYNt4cXTaxU0kZrC7LDNnO
AIULHXAzhedntLUTViD26w2VhvqOxAwXxarVRNQuKevG0JLjvD/kK5AoufeIpusr
kfNhP3sT9ITPI5P9G7nJSLl8CaLRa8DO8WxxMN/UBppwXBg4BfWqtfQG4GyW+8Xw
pF4dnJrywOtAuVWY2bZnb6CBJGd3JCAqgt+c+ROGM9HjromsfYu1vMgBZ6d9iZ29
EeQhkLGeISjXWDI6t9D8WCNEcWD7Fs7wPq1jmSdo9Dx7GU2kcoEjHB1S38Kgy7u/
nXSb6YcwkRX7pZy5Or2ATL2i/yf2Pu93z8dP5v099gJqcSajeIAxvdLf9A5kdGsr
x6VWZWYldA4CN963jEG7e8vXorF8+QZe9W7M7sZ/K7xHRapklo4i7QExL/WcLOE5
5e7amAiesYjTzqaQKouTY+UXLm9EG/Czjc1tMIaYr3WCxX92RSB1GB1AP2U/epmh
oL9AqPtoe4jT+xQPnipCypxRSn1xnZV90rgNusEiVaC5nhVlOHSABE2BEHi/xjTr
t1v2yzxSXn+g4+olx6iKzHRxR0yTt2duU63LjD8eFj2WxDs07O+31uWZ9BEHyPmP
8bELgEg0H9IqK2AJRyCGN1SFLi7yt5hekbk0CixZryScjPT2C6HLeca7ghEuRmvL
L6dv1rRM2pKKdrX1FtDkVntj2Evt4ngYJnVoK3EbIxxwAxHpv35h5RHYFowyO8kO
uttBvbEqOz8KZpprPbT3g9qlITyuRqULT8Yi+0+X6JIEJ0ayEDz8+1226R6osoGe
w5kwT8POQTrkMuutyO5huPKWMgLR74XM18tUHI5k/x/698C1QLtSXACtheteH5x+
nUKJOVTraScoX5DOE+kQ7D7FnRR1uJyQdh5+XcF6mZ1tcZcsDiu9HiUHD12xP1dM
wEqMyd6mBl1AxJVuf72aXBpSi7A58zeqKc7CdMovdm/uRVHzXHPcKUYy8fAtrJFN
OVJ7nZGLBVpSKroKXuM06PgR7QYrs42HmXopkD8w5h7qRJV8zxCc0iUl1dU7511f
MspTboffXGOkj+3jp80aAoWTm4axMvsklUN6zzxoNgsGUBmdv/twxtJzv8TLFFTz
I+WldMQ4JUINrWEHYSbYcgbn7MycvwLv9+f8a+I3KHQglRMk+LTulQLcU/wwM36e
4/F11Cr0NqjMp0jNRC6D+P7up9FHD2McXaCvtcXopWgmpa4RoGRl/IdmJtC+q3oF
Qomt71wLsgiv4J84mt+XKPfJhbJeaAcLRJAka2zk7KmLGkAKQYu1yMb480H5eOwF
Yck1Eh39ciLpysIPNnk7ZQ+t2dX/r3VrrMwnbrsFXzl14VsPJd7vLuh9nH8Zx8gS
fNVFCt/hB1mJ+zeTP6qgJiSLzjCn5lg85NzGDWela3F8CsVR3+7Qms4m66yqSFm+
QemTVykHMDke5IP1mFj3OA==
-----END ENCRYPTED PRIVATE KEY-----

Następnie warto sobie przygotować config do generowania CSR (certificate signing request), czyli żądanie podpisania certyfikatu, ja sobie zapisałem go w pliku o nazwie config.cnf. Istotne w tym szablonie są pola CN oraz DNS.1 – one muszą być adresem FQDN naszego hosta, na którym jest zainstalowany FSSO Collector (w sensie agent), w moim przypadku jest to fsso-collector.serba.local:

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C=PL
ST=SL
L=Tychy
O=it.supra.tf
OU=IT
[email protected]
CN = fsso-collector.serba.local

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = fsso-collector.serba.local

Mając coś takiego gotowe tworzymy sobie CSR poleceniem:

openssl req -new -sha256 -key local.key -out fsso-collector.serba.local.csr -config config.cnf

W ten sposób otrzymujemy coś takiego:

-----BEGIN CERTIFICATE REQUEST-----
MIIDEzCCAfsCAQAwgZUxCzAJBgNVBAYTAlBMMQswCQYDVQQIDAJTTDEOMAwGA1UE
BwwFVHljaHkxFDASBgNVBAoMC2l0LnN1cHJhLnRmMQswCQYDVQQLDAJJVDEhMB8G
CSqGSIb3DQEJARYScmFkb3NsYXdAc2VyYmEub3ZoMSMwIQYDVQQDDBpmc3NvLWNv
bGxlY3Rvci5zZXJiYS5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALjPgatD84GPdQlt5GytCUSjs7Mr4k3yn7mUW2QbEr9zAQ5/uRWo/rep6ptr
N2HBP4vFzCTGA4c1OGwg0yzzkz3uGEVUiJ0qdudutHGYEfDpr2Hd0kH6eH7MIqGx
GBqhe9+XRugtSojE2jDPGL3UU2eDhx8fzzovbbi+IyuOsOEtCwGl2FvPP9AnT2/s
owTOxlU2ZqaAauL+72pa0ciSdDfWh9Lat2FeWIPD34qAt/n9yK4fXpSWgWm0y+zB
ackruljZxd6gw4x0KBKdUq+a8vPdz6RK2ODBnQEG02DkxvdjfgzkzX2aNbR9QWAC
HuPGB6FdzidIf+UoBUaUKrFabhMCAwEAAaA4MDYGCSqGSIb3DQEJDjEpMCcwJQYD
VR0RBB4wHIIaZnNzby1jb2xsZWN0b3Iuc2VyYmEubG9jYWwwDQYJKoZIhvcNAQEL
BQADggEBADa3+JoA0OjayAo2e9IX232mHrzgPtF4B4IY61xQACuIsqQW7IoLIaR5
h5HyPhRENecWws6ORwBcnKvIJykuXj4H1PaacUiTQgkOIAPnSltjGIkA8cnvtQYA
RrsKx4QTgbtr64+1E2xFRN+3Z6cOwyDB8yhOCS2k4UnyuC5XSJsQySI0GFqGdVGl
wLsT8IYQRcMkvlih3g+7hARb9C9TNW/se/UN/xL/q3ssWZfZ3QRuphDpn1zYo5au
XeuIXilt+R3bDvW3o5ThyKta/mGSt0Zr01KxviNalHvqLSYXSf4eHErstimNrqJp
+l05rq3qpcmbTp6Rq7IJ5F4j6hp2axI=
-----END CERTIFICATE REQUEST-----

Takie coś musimy przesłać do naszego CA, a w wyniku tego dostaniemy certyfikat. Wchodzimy więc na stronę naszego urzędu certyfikacji (musimy się przedtem autoryzować naszym kontem administracyjnym):

Po tym wybieramy Żądanie certyfikatu.

Następnie zaawansowane żądanie certyfikatu.

Tutaj sprawa jest prosta – wklejamy naszą zawartość CSRki i wybieramy odpowiedni szablon certyfikatu. W skrócie jest kilka predefiniowanych w naszym CA, można je zmieniać z przystawki certification authority i szablon Serwer sieci Web jest do serwerów HTTP, więc w sam raz, bo jest właśnie ten nam tutaj potrzebny. Klikamy Prześlij >.

Tutaj musimy tylko pobrać sam certyfikat i musi być szyfrowany algorytmem Base-64. Często w certyfikatach potrzebne są nam certyfikaty CA (chain) oraz certyfikat serwera (certificate). W niektórych serwerach wystawia się je w jednym pliku, przy czym najpierw jest zawartość certyfikatu serwera, a potem certyfikat CA (takie pliki są określane mianem fullchain). Tutaj wystarczy sam certyfikat serwera, a plik certyfikatu CA musi być dodany na naszym FortiGate. Taki można wrzucić tutaj:

Następnie certyfikat serwera oraz klucz prywatny, który stworzyliśmy na samym początku musimy podać w ustawieniach zaawansowanych (przycisk Advanced Settings) FSSO collectora:

U góry wskazujemy plik certyfikatu, w środku plik klucza prywatnego oraz na dole podajemy hasło, jakie zdefiniowaliśmy dla tego klucza, po czym klikamy Test, a jak hasło jest prawidłowe to klikamy OK. Dodam, że warto odblokować na firewallu w Windowsie komunikację pomiędzy naszym FortiGate’m a hostem z agentem na porcie TCP 8001 w dwie strony, bo inaczej to nie zadziała.

Po stronie FortiGate musimy jeszcze w ustawieniach External Connectors zaznaczyć opcję Trusted SSL Certificate i wybrać CA, które podpisało ten certyfikat i teoretycznie wszystko powinno być okej…

…ale jednak nie. Okazuje się, że nawet w najnowszej wersji FortiOS po włączeniu tego FortiGate dalej próbuje się łączyć z wykorzystaniem SSLa do collectora po porcie 8000 zamiast 8001. Tego się dowiedziałem w trakcie troubleshootingu z supportem Fortinetu (który sam przyznał, że dodali taką funkcję, bo 1 klient o to poprosił, ale w sumie tego nie ma nigdzie opisanego), więc w skrócie taki port trzeba aktualnie zmienić w CLI:

anzena-forti (fsso) # show config user fsso
    edit "serba.local"
        set server "fsso-collector.serba.local"
        set port 8001   <======== w tym jest problem, trzeba to zmienić z 8000 na 8001
        set password ENC H7/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==
        set ssl enable
        set ssl-trusted-cert "SERBA-CA"
    next
end

Zmieniamy to poleceniami:

anzena-forti # config user fsso
anzena-forti (fsso) # edit serba.local
anzena-forti (serba.local) # set port 8001
anzena-forti (serba.local) # end

Po tym komunikacja FortiGate z FSSO Collectorem po SSLu będzie działać.

Na koniec dodam, że Pan z Fortinet TAC sprawdzał to za pomocą sniffera poprzez CLI wykonując polecenie:

diag sniff packet any "port 8000" 6 0 a

Poza tym włączał debug mode poleceniami:

di de en
di de authd fsso server-status

Update: po aktualizacji do wersji FortiOS 6.4.2 zauważyłem, że dodano wiele portów do profili FSSO:

anzena-forti (fsso) # edit serba.local

anzena-forti (serba.local) # 
set      Modify value.
unset    Set to default value.
get      Get dynamic and system information.
show     Show configuration.
next     Configure next table entry.
abort    End and discard last config.
end      End and save last config.
 
anzena-forti (serba.local) # set 
type                       Server type.
*server                     Domain name or IP address of the first FSSO collector agent.
*port                       Port of the first FSSO collector agent.
password                   Password of the first FSSO collector agent.
server2                    Domain name or IP address of the second FSSO collector agent.
port2                      Port of the second FSSO collector agent.
password2                  Password of the second FSSO collector agent.
server3                    Domain name or IP address of the third FSSO collector agent.
port3                      Port of the third FSSO collector agent.
password3                  Password of the third FSSO collector agent.
server4                    Domain name or IP address of the fourth FSSO collector agent.
port4                      Port of the fourth FSSO collector agent.
password4                  Password of the fourth FSSO collector agent.
server5                    Domain name or IP address of the fifth FSSO collector agent.
port5                      Port of the fifth FSSO collector agent.
password5                  Password of the fifth FSSO collector agent.
ldap-server                LDAP server to get group information.
group-poll-interval        Interval in minutes within to fetch groups from FSSO server, or unset to disable.
user-info-server           LDAP server to get user information.
ssl                        Enable/disable use of SSL.
ssl-trusted-cert           Trusted server certificate or CA certificate.
source-ip                  Source IP for communications to FSSO agent.
source-ip6                 IPv6 source for communications to FSSO agent.
interface-select-method    Specify how to select outgoing interface to reach server.

Poniżej przykład mojej konfiguracji:

config user fsso
    edit "serba.local"
        set server "dc1.serba.local"
        set port 8001
        set password ENC 2ADfLnGWaMcPrHrwp8gIddCjZsNg9EsPidsh4Gdy+eWPIi0GC6Dycw74/LqRRZNgpZJT44X9X6EpZV4qE3gCI01pgo5xUk4B0sqQGd+6YObAZEBvwT2vBzNFNXNI9ZZX2Db+n0GmrNIUECD0bUhDUalmZeeIqa341M0YirrJAJ+bv9AAgsMB891F77JpX4QNqzV4Gg==
        set server2 "dc2.serba.local"
        set port2 8001
        set password2 ENC BJJKjYuknd0U+rMXrzjS8DLcgENw8aE+kW2gKipuXxh+gJYHB1TAdpr4GNDXRWY7/gSe5K0lrl8Y7L7fS2EHTJMsJx/MZ1q8NL2qSbAk7sZpkXMmFlSOBwXUg9RKN9eH/6TT6f1CZLOHc6vqjT11XXbdrKNgy6y9wNCipuef+PKK9OMrlxxh/yQjJ2TvA7rrPvP+Bg==
        set ssl enable
        set ssl-trusted-cert "SERBA-CA"
    next
end

Dobre configi w Team Fortress 2 – najczęstsze problemy i rozwiązania

W tym edytuję configi. W sumie to cokolwiek. Visual Studio Code, polecam.

Sporo osób mnie pytało o to jak sobie z tym poradzić, niektórzy nawet sprzedają własne configi (XD), więc stwierdziłem, że postaram się trochę z tym pomóc raz na zawsze. Postaram się wyjaśnić jak ogólnie configi działają, co jeśli używacie MasterComfiga, jak ustawić configi na osobnych klasach i dam kilka przykładów z mojego setupu.

Czy Twój config jest najlepszy?

Odpowiedź jest prosta: nie. Dla mnie jest on najlepszy, ale to nie znaczy, że taki ma być dla każdego. Dostosowałem swój config do swojego sprzętu, dlatego mi tak pasuje. Nie każdy tak jak ja ma klawiaturę ze średnim rozmiarem (to znaczy mam strzałki i klawiaturę numeryczną połączoną razem) czy myszkę ze strzałkami back/forward (które wykorzystuję też w grze). Najlepszy config, który jest dla Ciebie to taki, który Ci samemu najbardziej odpowiada. Coś Ci nie pasuje? Zmień to i sprawdź, czy teraz jest lepiej. W ten sposób możesz własną drogą dotrzeć do najlepszego configu.

Tak to wygląda u mnie.

W czym najlepiej edytować configi?

W tym, co lubisz. Ja osobiście polecam Visual Studio Code – działa na Windowsie i na Linuksie (pozdro Kartky), najważniejsze w nim jest to, że podkreśla składnie i ma kilka tricków, które pozwala nam łatwiej znaleźć błędy w składni, szybko coś skopiować i podmienić. Niektórzy boomerzy używają Notepada++ i to jest okej – wszystko jest lepsze od Notepada, który nie ma podkreślania składni (syntax highlighting). Wiadomo, jak ktoś używa Linuksa to tam prawie każdy edytor tekstu ma podkreślanie składni i tam nie ma o co się martwić. Na dobrą sprawę w czymkolwiek można edytować configi. Kwestię macOSa przemliczę – od 10.15 Catalina nie da się odpalać aplikacji 32-bitowych natywnie, więc nie pogracie sobie tak łatwo w TFa (jest opcja Wine, ale to ponoć jest dramat).

Okej, no to jak to działa?

Działa to tak:
Najczęściej operujemy na takich configach:

  • config.cfg – główny config gry, w nim są przechowywane aktualne ustawienia. Jeśli coś ustawiliście w grze (np. z konsoli) to takie rzeczy pewnie będą tutaj, nie wprowadzamy tutaj zmian, ten config jest odpalany w pierwszej kolejności. Jeśli mamy zdefiniowane jakieś ustawienia na konkretnej klasie i zamkniemy grę – one będą też w tym configu.
  • autoexec.cfg – ten config zawiera wszystkie nasze rzeczy, które chcemy mieć skonfigurowane i odpala się po config.cfg, tutaj wykonujemy wszystkie zmiany, które nas interesują.
  • scout.cfg – config z ustawieniami dla Skauta.
  • soldier.cfg – config z ustawieniami dla Żołnierza.
  • pyro.cfg – config z ustawieniami dla Pyro.
  • demoman.cfg – config z ustawieniami dla Demomana.
  • heavyweapons.cfg – config z ustawieniami dla Grubego.
  • engineer.cfg – config z ustawieniami dla Inżyniera.
  • medic.cfg – config z ustawieniami dla Medyka.
  • sniper.cfg – config z ustawieniami dla Snajpera.
  • spy.cfg – config z ustawieniami dla Szpiega.
  • inne configi, które wrzucimy sami, np. jump.cfg – to, co w nich jest zależy od nas.

Configi klas włączają się w momencie wybrania klasy, więc jeśli zmienimy klasę na Snajpera, po prostu załaduje się sniper.cfg i to, co w nim jest.
Na dobry początek najłatwiej zacząć od obserwowania jakie configi mają inni – niby tutaj jest lista wszystkich ustawień w grze, ale komu by się chciało to przeglądać? Dlatego najlepiej jak zobaczycie, że ktoś używa jakiegoś innego celownika, ma np. podgląd klasy na dole w 3D itd. Potem połączcie to razem ze sobą i voilà – macie swój config. Tutaj znajdziecie więcej info o moim setupie.

Na wstępie powiem, że będę używał słowa zmienna (ang. variable). Te słowo określa jakieś konkretne ustawienie. Możemy je określać na różne sposoby, na przykład są ustawienia, w których musisz podać jakąś wartość (np. fov_desired 90) i im większa/mniejsza wartość tym ustawienie jest bardziej widoczne (w tym przykładzie większa wartość daje większe pole widzenia i maksymalna wartość to 90). Są też zmienne, w których określamy czy dane ustawienie ma być włączone czy nie. Jeśli jest włączone to dajemy 1, jeśli wyłączone to dajemy 0. Przykład: cl_autoreload 1 (w ten sposób mamy włączone automatyczne przeładowywanie broni). Wartości ustawień warto podawać w cudzysłowie, czyli np. zamiast fov_desired 90 dajemy fov_desired "90". Po co? W tym przypadku akurat to nic nie zmienia, ale jeśli wartość zawiera spację to wtedy polecenie może nie działać poprawnie (nie chcę dokładnie wyjaśniać dlaczego, chcę by ten poradnik był możliwie jak najprostszy do zrozumienia), więc można być trochę takim pedantem i dawać te cudzysłowie za każdym razem. Wtedy unikniemy problemów. W configach ustawiamy trzy rzeczy:

  • zmienne,
  • bindy,
  • aliasy.

Zmienne przedstawiłem już na samej górze. To jest coś, co oferuje nam gra jako ustawienie. Bind jest przypisaniem danej funkcji do przycisku, a alias alternatywną nazwą funkcji. Funkcja to jest w uproszczeniu coś, co wykonujemy – na przykład funkcja slot1 powoduje, że wybieramy broń pierwszorzędną dla naszej klasy. Alias jest alternatywną nazwą jakiegoś ustawienia lub zestawu kilku ustawień – np. możemy przypisać zmianę broni na pierwszorzędną oraz wyłączenie modelu w jednym poleceniu, przykład:

alias first "slot1; viewmodel_fov 0; r_drawviewmodel 1"

W ten sposób jak przypiszę taki alias do przycisku 1 (tego nad przyciskiem Q):

bind 1 "first"

Listę wszystkich przycisków można znaleźć tutaj. Ogólnie warto też przeczytać sobie tę stronkę w całości – jest tam mnóstwo podstawowych porad dotyczących robienia configów.

Jeśli chcemy mieć jakieś konkretne ustawienia, które mają działać na wszystkich klasach – wrzucamy do autoexec.cfg, jeśli takie ustawienia mają być na konkretne klasy – wrzucamy te same ustawienie do configu konkretnej klasy, np. ten sniper.cfg. Jeśli ustawiamy jakieś specyficzne ustawienie na konkretną klasę, na przykład przypisujemy ustawienie do prawego przycisku myszki to powinniśmy ustawić takie ustawienie na każdej klasie. Dajmy przykład tego prawego przycisku myszki – ja na skaucie i soldzie mam zmianę broni na ostatnią. Jeśli chcemy, by ten prawy przycisk myszki działał nam tak jak działał dotychczas to powinniśmy sprawdzić co mamy ustawione na tych klasach i wpisać to do configów tych klas. Prawy przycisk myszki to MOUSE2 na każdej myszce, więc sprawdza się to, co tam jest poleceniem bind MOUSE2:

] bind MOUSE2
"MOUSE2" = "+attack2"

Ostatnią broń wybiera funkcja lastinv. W takiej sytuacji na poszczególnych klasach dodajemy:

scout.cfg

bind MOUSE2 "lastinv"

soldier.cfg

bind MOUSE2 "lastinv"

pyro.cfg

bind MOUSE2 "+attack2"

demoman.cfg

bind MOUSE2 "+attack2"

heavyweapons.cfg

bind MOUSE2 "+attack2"

engineer.cfg

bind MOUSE2 "+attack2"

medic.cfg

bind MOUSE2 "+attack2"

sniper.cfg

bind MOUSE2 "+attack2"

spy.cfg

bind MOUSE2 "+attack2"

Tutaj te zmiany dla skauta i solda można zrobić lepiej. Prawy, lewy przycisk myszki i spacja mogą sterować kamerą jak się jest obserwatorem i warto je przypisać zamiast tak:

bind MOUSE2 "lastinv"

zrobiłbym to tak:

alias "attack2linv" "lastinv; spec_prev"
bind "MOUSE2" "attack2linv"

Warto do tej funkcji na prawym przycisku myszki dodawać spec_prev, bo w ten sposób nie odbieramy sobie możliwości przesuwania na tym przycisku. W przypadku lewego przycisku myszki dodaje się przycisk spec_next. W przypadku spacji dodaje się spec_mode.

Jak na danym przycisku chcecie mieć przycisk, który nie robi nic, np. na F4 nic nie potrzebujecie, dodajcie na tej klasie linijkę:

unbind F4

Po co te wszystkie przypisania na każdej klasie? Powiedzmy, że w configu pootisa nie wrzucimy takiego przypisania do prawego przycisku myszki. Jeśli zmienimy klasę to będzie na takim pootisie działało ustawienie z poprzedniej klasy i wtedy mogą wystąpić dwa przypadki:

  • jeśli poprzednia klasa, na której graliśmy miała bind bind MOUSE2 "+attack2" (na przykład Snajper) to nic się nie stanie,
  • jeśli poprzednia klasa miała inny bind na tym przycisku (np. sold i skaut w naszym przypadku ma bind MOUSE2 "lastinv" to pootis zamiast rozkręcać miniguna prawym będzie zmieniał broń. To jest słabe.

Jeszcze co do funkcji z + i - na początku, np. +forward – o co chodzi?
Funkcje z plusem są wykonywane, gdy przycisk jest wciśnięty, a z minusem, kiedy go puszczamy, więc +forward powoduje, że idziemy do przodu, a -forward powoduje, że przestajemy iść do przodu. To można wykorzystać np. przy tzw. winger jumpie, czyli skoku, w którym wykorzystujemy właściwość Wingera (pol. Skrzydłowy) na skaucie po to, by podskoczyć wyżej i z powrotem zmienić broń na Scatterguna (pol. Dubeltówka). Wtedy trzeba zrobić dwa aliasy: z plusem i minusem, a potem do przycisku przypisać alias z plusem, a gra sama będzie wiedziała, że ta z minusem też istnieje, przykład:

alias +wjump "slot2; +jump; +duck"
alias -wjump "lastinv; -jump; -duck"
bind MOUSE5 "+wjump"

Jak testować configi?

To dosyć proste. Wpisujecie w konsoli exec naszconfig i w ten sposób sprawdzacie wyniki. Zmiany są najczęściej widoczne natychmiast. Mało tego exec naszconfig może być umieszczony w innym configu, więc jeśli ktoś w tym widzi jakieś rozwiązanie to też z tego można skorzystać.

Gdzie te całe configi są?

W dwóch miejcach:

  • C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf\cfg – zakładając, że nie używacie MasterComfig,
  • C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf\cfg\user – zakładając, że używacie MasterComfig (w najnowszej wersji, starsze wersje wymagały dziwnych zmian z postfiksem _c.cfg na końcu nazwy pliku oraz zmianę autoexec.cfg na custom.cfg, teraz to już przeszłość.

tl;dr jak ustawić nagrywanie demek?

Wszystkie composzczury compowcy tego muszą używać na meczach czy tego chcą, czy nie. Są dwie opcje jak można nagrywać demka:

  • P-REC (plugin napisany przez pewnego Ukraińca) – poradnik jest napisany tutaj i nie chcę mi się go przepisywać na polski, bo on jest naprawdę banalnie prosty. Jeśli go używacie to nie możecie wchodzić na gierki competitive wbudowane w grę (z których i tak nikt nie korzysta, więc w sumie żadna strata).
  • Demo Support, czyli wbudowany w grę mechanizm do nagrywania demek. Powstał po to, by ludzie nie używali P-RECa, ale w rzeczywistości ludzie z Valve nawet to potrafili spierdolić. Z tego aktualnie korzystam.

Oba programy mają swoje wady i zalety. W przypadku P-RECa zaletą jest to, że demka są nagrywane od początku gry do końca, poza tym P-REC sam robi screenshoty statusu (polecenia status, to jest potrzebne na meczach ETF2L). DS nagrywa demka od wejścia na serwer, więc całą naszą rozgrzewkę też nagra (wiadomo, przecież wtedy strzela się najpotężniejsze airshoty to trzeba się jakoś pochwalić, c’nie?). Z drugiej strony w DSie nie trzeba nic instalować – kilka poleceń i działa, poza tym nie psuje gry.

Wszystkie polecenia do DSa:

ds_autodelete "0" //wyłączone automatyczne usuwanie nagranych demek, usuwajmy je ręcznie dzięki czemu na offi nie będzie sytuacji, że zapomnieliśmy nagrać i kapa
ds_dir "suprademos" //wrzuca wszystkie nagrane demka do folderu suprademos, który jest w folderze tf (w moim przypadku "C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf")
ds_enable "3" //0 wyłącza DS, 1 nagrywa gierki z compa wbudowanego w tfa, 2 nagrywa wszystko (casual/community serwery też), 3 nagrywa te prawdziwe mecze comp
ds_kill_delay "10" //w tym przypadku po 10 sekundach od niezabicia fraga killstreak się nie nalicza
ds_log "1" //ta opcja włącza zapisywanie wszystkich bookmarków (automatycznych i ręcznych) do pliku tekstowego
bind F6 "ds_mark" //dzięki temu po wciśnięciu F6 robi się nam bookmark w trakcie gry
ds_min_streak //minimalny killstreak, jaki musimy osiągnąć, by DS sam zrobił nam bookmarka
ds_notify 2 //wyświetla info o poprawnym zrobieniu bookmarka, 0 powoduje wyświetlanie w konsoli, 1 w konsoli i na czacie, 2 w konsoli i na środku ekranu (HUD)
ds_prefix "" //można zostawić puste, to co wpiszemy tutaj będzie na początku każdego pliku demka czy zrzutu ekranu
ds_record //bezużyteczne, po prostu odpala nagrywanie demka
ds_screens 1 //robi screenshota po końcu gry, jeśli wyjdziemy wcześniej z meczu to zapomnijcie o screenie
ds_sound 1 //jak się zaczyna nagrywanie demka to słyszymy dzięki temu dźwięk
ds_status //bezużyteczne, wyświetla w konsoli czy demko nam się nagrywa
ds_stop //bezużyteczne, zatrzymuje nagrywanie demka (robi to samo co polecenie stop)

Tutaj na przykład możemy dać inne killstreaki na inne klasy, np. na medyka dałbym 1, a na snajpera na przykład 3. Wszystko jest kwestią własnego gustu. Najważniejsze jest to, by samemu przetestować czy nagrywanie demek/robienie screenshotów działa.

Udało mi się też wykopać mój stary config do P-RECa:

prec_mode 3
prec_dir suprademos
prec_notify 2
prec_screens 1
prec_delete_useless_demo 1 //wtedy usuwałem demka automatycznie
prec_tag ""
bind F6 prec_mark

Ogólnie z tym autousuwaniem demek są dwa rozwiązania: albo mamy włączone automatyczne usuwanie i zawsze robimy bookmark na początku każdego nagrywanego demka (jak w środku meczu nas wywali i wrócimy na serwer to znowu musimy zrobić bookmark, inaczej można dostać bana jak MattJ za nagranie niecałej mapy) albo mamy wyłączone automatyczne usuwanie i usuwamy niepotrzebne demka ręcznie. Sami się zastanówcie co jest lepszym rozwiązaniem dla Was.

Aliasy na przyspieszenie zmian

Prosta sprawa, dodajecie to do autoexec.cfg i efekt jest taki, że żeby zmienić mapkę na zarezerwowanym przez Was serwerze (zakładam, że macie wpisane hasło do rcona w konsoli) wystarczy wpisać nazwę mapy, na przykład granary.

alias "reckoner" "rcon changelevel cp_reckoner_rc2"
alias "badlands" "rcon changelevel cp_badlands"
alias "prolands" "rcon changelevel cp_prolands_b6"
alias "process" "rcon changelevel cp_process_final"
alias "snake" "rcon changelevel cp_snakewater_final1"
alias "gully" "rcon changelevel cp_gullywash_final1"
alias "granary" "rcon changelevel cp_granary_pro_b8"
alias "product" "rcon changelevel koth_product_rcx"
alias "metalworks" "rcon changelevel cp_metalworks"
alias "sunshine" "rcon changelevel cp_sunshine"
alias "bwater" "rcon changelevel pl_badwater"
alias "bwaterpro" "rcon changelevel pl_badwater_pro_v12"
alias "coalplant" "rcon changelevel koth_coalplant_b8"
alias "warmtic" "rcon changelevel koth_warmtic_b6"
alias "upward" "rcon changelevel pl_upward"
alias "lake" "rcon changelevel koth_lakeside_final"
alias "swift" "rcon changelevel pl_swiftwater_final1"
alias "ash" "rcon changelevel koth_ashville_rc1"
alias "barnblitz" "rcon changelevel pl_barnblitz_pro6"
alias "steel" "rcon changelevel cp_steel"
alias "borneo" "rcon changelevel pl_borneo"

Innym fajnym aliasem jest:

alias "tv" "rcon tv_delaymapchange_protect 0"

Często po skończeniu się mapy chcemy od razu zmienić ja na następną, ale domyślnie SourceTV to blokuje, więc mając taki alias w naszym autoexecu wpisujemy w konsoli tv oraz nazwę nowej mapy i jest po temacie.

Zmiany klas (to sobie skopiowałem od thaza) – klikasz odpowiedni przycisk na klawiaturze numerycznej i zmieniasz na klasę, której potrzebujesz + informujesz ludzi na czacie o tym, bardzo przydatne na 6v6:

bind "KP_END" "join_class scout; say_team is scout"
bind "KP_DOWNARROW" "join_class soldier; say_team is soldier"
bind "KP_PGDN" "join_class pyro; say_team is pyro"
bind "KP_LEFTARROW" "join_class demoman; say_team is demoman"
bind "KP_5" "join_class heavyweapons; say_team is vladimir pootis"
bind "KP_RIGHTARROW" "join_class engineer; say_team is engineer"
bind "KP_HOME" "join_class medic; say_team is medic"
bind "KP_UPARROW" "join_class sniper; say_team is sniper"
bind "KP_PGUP" "join_class spy; say_team is spy"

Bindy do serwerów – przydatne jeśli chcę wejść szybko na konkretny serwer, na którym często gram:

alias "mge" "connect melkor.tf:27030"
alias "mge2" "connect melkor.tf:27035"
alias "dm" "connect melkor.tf:27050"
alias "bball" connect supra.tf:27025"
alias "supra" "connect supra.tf; password dupa69"

Jeśli macie jakieś ciekawe bindy czy aliasy to podeślijcie mi je w wiadomościach prywatnych lub w komentarzach – jeśli uznam, że są naprawdę przydatne to dodam je na końcu tego posta.

Mój setup w Team Fortress 2

Nie chodzi mi o przedmioty, lecz o konfigurację. Sporo osób mnie pyta o to z czego korzystam, więc postaram się odpowiedzieć raz na zawsze tym postem na te pytanie.

MasterComfig

Aktualnie (w 2020) najlepsze configi pod kątem optymalizacji gry. Wystarczy wejść tutaj, wybrać odpowiedni preset i dodatkowe modyfikacje. Ja używam presetu Low.

Następnie wybieram takie dodatki:

Potem wystarczy kliknąć Download Low preset and selected addons VPKs (wystarczy kliknąć w przeglądarce zgodę na pobranie wielu plików). Jeśli to nie działa, pobierz po prostu wszystkie pliki po kolei poniżej.

Potem wystarczy te pliki wkleić do folderu C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf\custom:

HUD

Korzystam z Hypnotize Huda, który można pobrać tutaj. Jest całkiem ładny, nie ma oczojebnych kolorków i jest czytelny. Po ściągnięciu rozpakowujemy katalog z HUDem i w folderze customizations znajdziemy mnóstwo opcji ustawienia innej opcji HUDa. Na przykład Pause Menu, możemy sobie zobaczyć w Pause Menu Background.png jak wyglądają opcje, a w Pause Menu Background.res można te opcje przestawić.

Ja włączam transparent background, big team status, full stats scoreboard, i quake font. Pliki po zmianie wyglądają tak:

Pause Menu Background.res

//#base "../resource/ui/PauseMenuGrey.res"				// DEFAULT GREY BACKGROUND
#base "../resource/ui/PauseMenuTransparent.res"		// TRANSPARENT BACKGROUND

Team Status.res

//#base "../resource/ui/HudMatchStatus_SmallHealth.res"		// SMALL HEALTH BAR TEAM STATUS
#base "../resource/ui/HudMatchStatus_BigHealth.res"		// BIG HEALTH BAR TEAM STATUS

Scoreboards.res

//#base "../resource/ui/Scoreboard_NoStats.res"			// SHORT STATS SCOREBOARD
#base "../resource/ui/Scoreboard_FullStats.res"		// FULL STATS SCOREBOARD

Alternative Fonts.res

//#base "../resource/scheme/Fonts_Avenir.res"
//#base "../resource/scheme/Fonts_Cerbetica.res"
//#base "../resource/scheme/Fonts_Neutra.res"
//#base "../resource/scheme/Fonts_Nexa.res"			//DEFAULT HYPNOTIZE HUD FONT
//#base "../resource/scheme/Fonts_Product.res"
#base "../resource/scheme/Fonts_Quake.res"
//#base "../resource/scheme/Fonts_Renogare.res"
//#base "../resource/scheme/Fonts_Roboto.res"
//#base "../resource/scheme/Fonts_Surface.res"
//#base "../resource/scheme/Fonts_TF2.res"

Poza tym dodaję też tło do numerków z HP i amunicją. W folderze Health & Ammo Box Overrides znajduje się folder resource i scripts. To musimy skopiować i wkleić w głównym katalogu HUDa:

No explosion smoke script

Znalazłem to tutaj. Wystarczy, że wkleicie wszystkie pliki .txt do folderu scripts wewnątrz folderu swojego HUDa (na przykład tego, co przygotowaliście wcześniej). Ułatwiłem szukanie w tym poście, bo wystarczy, że ściągniecie sobie paczkę stąd i jej zawartość rozpakujecie tutaj:

Działanie tych skryptów jest takie, że usuwają fragment splasha (rozprysku) rakiety oraz dym po wybuchu. Poniżej pokażę jak to wygląda:

Bez skryptów
Ze skryptami

Niestandardowy hitsound i killsound

Używałem tego hitsounda i tego killsounda, teraz używam tego hitsounda i killsounda. Hitsound to dźwięk, który słyszymy jeśli trafimy przeciwnika, a killsound to ten, kiedy kogoś zabijemy. By z nich skorzystać, należy w folderze HUDa stworzyć sobie folder sound, następnie w nim ui i w nim umieścić pliki.

Na samym końcu wrzucamy folder hypnotize hud do folderu C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf\custom:

Parametry startowe gry

Wykorzystuję następujące parametry:

-window -noborder -w 1920 -h 1080 -nojoy -novid -nosteamcontroller -nostartupsound -nod3d9x

Przy pierwszym uruchomieniu dodajcie -dxlevel 81 – to zmieni wersję używanego DirectXa na 8.1. Po tym pierwszym uruchomieniu usuńcie ten parametr z listy. Korzystam z -dxlevel 81, bo dzięki temu nie występuje bug z nakładką Mumble, w którym cała nakładka jest biała.

Ustawienia znajdziemy tutaj:

I na dole Ustaw opcje uruchamiania…

Ostatnia i najważniejsza rzecz – configi!

Tutaj chyba się trochę rozpiszę. Pozostawiłem komentarze w blokach, poniżej fragment pliku autoexec.cfg:

cl_interp_ratio "1"
fps_max 0 //powinno się ustawiać 2x częstotliwość odświeżania ekranu + 1, więc mam 2x144+1=289, ale w moim przypadku lepiej było wyłączyć lock, warto potestować
tf_use_match_hud "1"
unbind numlock
bind "KP_END" "join_class scout; say_team is scout" //zmienia klasę na skauta i pisze na czacie teamowym "is scout" klasy są od skauta do spy na przyciskach na przyciskach numerycznych od 1 do 9
bind "KP_DOWNARROW" "join_class soldier; say_team is soldier"
bind "KP_PGDN" "join_class pyro; say_team is pyro"
bind "KP_LEFTARROW" "join_class demoman; say_team is demoman"
bind "KP_5" "join_class heavyweapons; say_team is vladimir pootis"
bind "KP_RIGHTARROW" "join_class engineer; say_team is engineer"
bind "KP_HOME" "join_class medic; say_team is medic"
bind "KP_UPARROW" "join_class sniper; say_team is sniper"
bind "KP_PGUP" "join_class spy; say_team is spy"
bind KP_ENTER "taunt_by_name Shred Alert; say gj bruh"
bind KP_MULTIPLY "taunt_by_name Taunt: The Schadenfreude; say ha ha h a h a"
alias "mge" "connect melkor.tf:27030" //wpisujesz mge w konsoli i jesteś na melkor #1 MGE
alias "mge2" "connect melkor.tf:27035" //wpisujesz mge w konsoli i jesteś na melkor #2 MGE
alias "dm" "connect melkor.tf:27050" //wpisujesz mge w konsoli i jesteś na melkor DM
alias "tutajpomarancza" "connect supra.tf:27020; password supersecretpassword"
snd_mute_losefocus "1" //jak zminimalizujesz grę to nie ma dźwięku
cl_hud_playerclass_use_playermodel "1" //włącza sylwetkę gracza w 3d w miniaturce postaci, dzięki temu można na 6v6 sprawdzać jakie klasy ma przeciwnik na spaju
cl_use_tournament_specgui "1" //dzięki temu jak oglądasz comp gierkę ze spectów to widzisz po lewej i prawej stronie punkty życia graczy
sv_lan "0"
closecaption "1" //dzięki temu są teksty w stylu scout bleeding po prawej stronie ekranu
crosshair "1"
voice_enable "1" //włącza czat głosowy
bind "h" "+use_action_slot_item"
bind F11 explode //killbind
r_drawdecals "0" //wyłącza spraye
hud_combattext "1" //włącza info o zadawanym dmg
hud_combattext_healing "1" //włącza info o leczeniu
tf_dingalingaling "1"
tf_dingaling_volume "1.000000"
tf_dingaling_pitchmindmg "128.529999"
tf_dingaling_pitchmaxdmg "20.110001"
tf_dingalingaling_lasthit "1"
tf_dingalingaling_last_effect "0"
tf_dingaling_lasthit_volume "1.000000"
tf_dingaling_lasthit_pitchmindmg "100.000000"
tf_dingaling_lasthit_pitchmaxdmg "100.000000"
tf_dingalingaling_repeat_delay "0.008"
cl_crosshair_red "0.000000"
cl_crosshair_green "255.000000"
cl_crosshair_blue "0.000000"
cl_crosshair_file "crosshair3"
cl_crosshair_scale "48.000000" //dzięki tych linijkom z cl_crosshair zawsze mam ten sam hud, czyli duże, zielone kółko
tf_remember_activeweapon "0"
tf_remember_lastswitched "0"
m_rawinput "1" //bezpośredni odczyt z myszki, dzięki temu unikamy efektu akceleracji myszki
cl_playerspraydisable 1
r_spray_lifetime 0
alias shit "say 0       ...; bind F10 shit2" //śmieszny bind
alias shit2 say "|\_ .`   `.; bind F10 shit3"
alias shit3 say "/\       open; bind F10 shit"
bind "F10" "shit"
bind "F12" "say www.wikihow.com/Deal-With-Your-Teenage-Anger try using it"
alias "tv" "rcon tv_delaymapchange_protect 0" //wpisujesz w konsoli tv i od razu możesz zmienić mapkę
alias "change" "bind space +jump"
alias "mixvote" "rcon sm_votemap" "cp_prolands_b6" "koth_product_rcx" "cp_snakewater_final1" "cp_gullywash_f2a" "cp_sunshine"
alias "reckoner" "rcon changelevel cp_reckoner_rc6"
alias "badlands" "rcon changelevel cp_badlands"
alias "prolands" "rcon changelevel cp_prolands_b6"
alias "process" "rcon changelevel cp_process_f7"
alias "snake" "rcon changelevel cp_snakewater_final1"
alias "gully" "rcon changelevel cp_gullywash_f2a"
alias "granary" "rcon changelevel cp_granary_pro_b8"
alias "product" "rcon changelevel koth_product_rcx"
alias "metalworks" "rcon changelevel cp_metalworks"
alias "sunshine" "rcon changelevel cp_sunshine"
alias "bwater" "rcon changelevel pl_badwater"
alias "prowater" "rcon changelevel pl_prowater_b12"
alias "coalplant" "rcon changelevel koth_coalplant_b8"
alias "warmtic" "rcon changelevel koth_warmtic_b6"
alias "upward" "rcon changelevel pl_upward"
alias "lake" "rcon changelevel koth_lakeside_final"
alias "swift" "rcon changelevel pl_swiftwater_final1"
alias "ash" "rcon changelevel koth_ashville_rc1"
alias "barnblitz" "rcon changelevel pl_barnblitz_pro6"
alias "steel" "rcon changelevel cp_steel"
alias "borneo" "rcon changelevel pl_borneo"

//p-rec support
//prec_mode 3
//prec_dir demos
//prec_notify 2
//prec_screens 1
//prec_delete_useless_demo 1
//prec_tag demkasupry
//bind F6 prec_mark
//built-in demo support
ds_enable 3
ds_min_streak 25 
ds_kill_delay 5 
ds_notify 2
ds_prefix "supra_demo_"
ds_screens 1
ds_sound 1
ds_autodelete 1
ds_dir "suprademos"
ds_log 1

rcon_address supra.tf:27015
rcon_password hahahahaha

Poniżej są zmienne, które i tak ustawiają jakość obrazu na niską i mam to dlatego, bo jestem leniwy i się przyzwyczaiłem to tych kiepsko wyglądających tekstur 😉

Configi można pobrać tutaj. Wystarczy wkleić zawartość tego zipa do folderu C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf\cfg i to tyle. Będzie działać. W przypadku używania MasterComfiga należy przechowywać configi klas oraz autoexec.cfg w folderze user będącym w cfg. Jeśli nie macie MasterComfiga, po prostu wrzućcie configi z user do folderu cfg i będzie działało.

autoexec.cfg jest ładowany w momencie uruchomienia gry. Pliki klas takie jak np. scout.cfg są ładowane w momencie wybrania takiej klasy. Na każdej klasie oprócz inżyniera możemy sobie zmieniać loadouty dla danej klasy: F1 – daje set A, F2 – set B, F3 – set C, F5 – set D. Nie używam F4 w configu, bo używa się go do kliknięcia Ready up w przypadku serwerów competitive/MVM.

W przypadku inżyniera te przyciski dają: F1 – działko, F2, dispenser, F3 – teleport (wejście), F5 – teleport (wyjście).

Medyk też jest na swój sposób wyjątkowy, bo u mnie loadouty są przygotowane pod konkretne mediguny: F1 – medigun, F2 – kritzkrieg, F3 – quickfix, F5 – vaccinator. Configi, które są w katalogu wyżej od user są do załadowania ustawień. Na przykład w przypadku Vaccinatora nie używam informacji na czacie, że użyłem, bo spamowałbym tym non-stop w trakcie normalnej gry.

Na soldzie i skaucie na prawym przycisku myszy mam zmianę broni. Pewnie kiedyś tam ustawię na soldzie skok, bo to jest lepsze rozwiązanie, ale póki co jestem leniwy.

Poza tym, jak możecie zauważyć na niektórych klasach jest włączony model broni na niektórych broniach, a na niektórych nie. Włącza/wyłącza się model przyciskiem danej broni, czyli np. na soldzie wciśnięcie 1 da nam zmianę na wyrzutnię rakiet + wyłączy nam model broni. W niektórych klasach działa to dosyć specyficznie, ponieważ na pyro i medyku mam wyłączony model mediguna, ale mam wyłączony strumień by widzieć czy kogoś leczę lub palę na pyro. Ten strumień pozwala mi łatwiej określić, czy ktoś jest w moim zasięgu (przynajmniej ja mam takie wrażenie).

Ponadto, w tym configu jest włączone automatyczne nagrywanie demek z competitive z usuwaniem demek bez bookmarków i demka są zapisywane do folderu suprademos (w folderze tf). Na F6 jest przypisany bind do robienia bookmarków.

Ktoś się mnie też pytał o zmienną, która powoduje, że grając medykiem nad każdym wyświetla się chmurka, dzięki czemu można tak jakby widzieć swoich kumpli z teamu za ścianami i robić prefire z kuszy, by kogoś szybko podleczyć. Ta zmienna to hud_medicautocallersthreshold "150".

Fajne skrypty specyficzne dla klas

Winger jump: powoduje, że skaczemy wyżej wykorzystując właściwość Wingera na moment. Naciskasz przycisk i postać sama zmienia broń i podskakuje. Skrypt wygląda tak (ja mam ten jump przypisany pod mouse5).

alias +wjump "slot2; +jump; +duck"
alias -wjump "lastinv; -jump; -duck"
bind "mouse5" "+wjump"
Bez winger jumpa
Z winger jumpem

Detonator jump:

To jest skrypt, który pozwala pod jednym przyciskiem robić jumpa na racy z detonatora. Naciskasz przycisk i za Ciebie robi cały jump, jedynie musisz odpowiednio kierować celownikiem, by lecieć tam, gdzie chcesz.

alias +detonatorjump "+jump;+duck;+attack;+attack2"
alias -detonatorjump "-jump;-duck;-attack;-attack2"
bind "mouse5" "+detonatorjump"

Nakładka (overlay) Mumble

Dzięki temu widzę, kto do mnie mówi na czacie głosowym lepiej. Ten domyślny jest w górnym, prawym rogu i wygląda kiepsko. Tło zasłania grę. Dlatego ja mam własną ścieżkę, własne kolory i ustawienie. Ustawiam nakładkę po prawej stronie na środku i działa ona tak, że mówiące osoby wyświetlają się tekstem na czerwono, jeśli przestaną mówić to mają taki szarawy kolor i po kilku sekundach od ciszy znikają z overlaya. W ten sposób też nie wyświetla mi zawsze wszystkich osób na kanale. Do tego mam przygotowany gotowy layout i konkretną czcionkę, którą używam.

Po prawej widać ten overlay.

By wgrać ten overlay, po pobraniu najlepiej wcześniej zainstalować sobie taką czcionkę, jaką jak mam i należy otworzyć ustawienia Mumble i w zakładce Nakładka (Overlay) kliknąć Wczytaj… w sekcji Opcje. Następnie za pomocą kropek trzeba ustawić w odpowiednim miejscu nakładkę. Aktualnie jej ustawienie wyrównuje nazwy użytkowników do lewej strony i to można sobie zawsze zmienić.

Następnie, jeśli chcemy zmienić czcionkę, robimy to tak, jak na animacji poniżej. Po tym można zapisać ustawienia.

Wyłączenie nakładki Steam w grze i przeglądarki w Steamie

Ten numer mi sprzedał wonszu i szczerze powiedziawszy to nawet z moim sprzętem zmiana jest zauważalna na plus. Po pierwsze, trzeba wyłączyć nakładkę Steam podczas gry (klikając prawym na grę -> Właściwości…:

Następnie należy sobie utworzyć skrót do Steama na pulpicie wchodząc do folderu ze skrótami (oczywiście to nie jest jedyne rozwiązanie, ale moim zdaniem jest najprostsze):

Otworzy nam się okno, stąd kopiujemy skrót na Pulpit:

Następnie klikamy na niego PPM -> Właściwości i w sekcji Element docelowy dodajemy parametry -console -no-browser. Zakładając, że macie zainstalowanego Steama w domyślnej lokalizacji to powinno wyglądać tak: "C:\Program Files (x86)\Steam\Steam.exe" -console -no-browser

iRedMail, LDAP i migracja serwera pocztowego, z której się sporo nauczyłem

Ten post nie będzie do końca taki, jak wcześniej, bo niestety nie mam tyle czasu, by opisać całą instalację iRedMaila i tego, co robiłem. Ogólnie udało mi się zmigrować u klienta serwer pocztowy. Klient miał Debiana 6, trochę stary, użytkownicy lokalni, a nie w SQLu czy LDAPie (OpenLDAP lub AD) i trzeba było coś z tym zrobić. Był to jakiś pakiet, który bazował na Postfixie/Dovecot z interfejsem webowym Squirrel. Trzeba było coś z tym zrobić, więc ostatecznie zdecydowaliśmy się na migrację serwera na nowy, z Debianem 10 i celem był iRedMail – prosty pakiet z Postfixem i Dovecotem z podstawowym panelem administracyjnym. Wdrożyłem go z LDAPem z prostego powodu: jest szansa na to, że w przyszłości taki użytkownik będzie mógł wykorzystać logowanie z Active Directory jeśli przepnie się query z LDAPa do AD oraz każdemu użytkownikowi w AD doda się odpowiedni atrybuty, z których korzysta iRedMail.

Dlatego też jeśli chcecie się nauczyć stawiać iRedMaila – polecam sobie poczytać ich dokumentację. Jest tam naprawdę sporo ciekawych materiałów. Pomimo to są rzeczy, które nawet jeśli są w tej dokumentacji przykuły moją uwagę.

Migracja użytkowników do OpenLDAPa

Użytkownicy byli przechowywani lokalnie, więc mogłem znaleźć ich nazwy użytkowników, nazwy wyświetlane (Gecos) itd w pliku /etc/passwd. Ogólnie ten plik wygląda tak:

root:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeee
supra:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee/:17604:0:99999:7:::
anotheruser:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee.:17604:0:99999:7:::
editor:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee.:17668:0:99999:7:::
test:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee.:18314:0:99999:7:::

Tutaj znalazłem informację jak tworzyć użytkowników w LDAPie z odpowiednimi atrybutami. Z tego pliku wyciągnęliśmy listę wszystkich użytkowników oraz Gecos. Wystarczy do tego Excel lub inny program pracujący z arkuszami kalkulacyjnymi, który jest w stanie zczytywać dane z plików, które mają oddzielone wartości za pomocą jakiegoś znaku (np. CSV). Na początku klikamy Z pliku tekstowego/CSV, następnie wskazujemy plik i wybieramy ogranicznik (znak oddzielający wartości, ang. delimiter), powinien być nim dwukropek.

Korzystam z Excel 2019 i on sam wykrył ten znak (musiałem jedynie zmienić kodowanie pliku na UTF-8), zmieniłem też pole Wykrywanie typu danych na Nie wykrywaj typów danych:

Jak widać, wszystko ładnie się zaimportowało:

Następnie należy trochę przerobić te dane. Składnia to:

mydomain.com, user2, plain_password, Michael Jordan, group1:group2,

W praktyce to powinno wyglądać tak:

Jak widać w stosunku do zrzutu ekranu wyżej, usunąłem przecinki po w nazwie wyświetlanej oraz poprzenosiłem wartości w kolejności. Kolumna F jest pusta, bo nie mam zdefiniowanych żadnych grup. W takiej sytuacji trzeba na końcu każdej linii po wyeksportowaniu pliku CSV dopisać spację i przecinek. Dodałem też te liczby i 5368709120 to jest quota (przydział rozmiaru skrzynki) w bajtach. 5368709120 daje nam 5 GB.

Zapisujemy plik w postaci CSV UTF-8 (w ogóle to jest dostępne tylko w Excel 2019, nie wiedzieć czemu):

Otrzymujemy to (otwieram takie pliki w Visual Studio Code):

Podmieńmy sobie najpierw średniki ; na przecinki ze spacją , :

Teraz musimy jakoś dodać te puste pola grup. Z faktu, że przypisałem wszystkim użytkownikom taką samą wielkość skrzynki, wykorzystam to, by dodać dodatkową wartość:

W ten sposób możemy wykorzystać taki plik CSV do zaimportowania użytkowników. Jak widać, nie przenoszę tutaj haseł tylko generuję nowe. Skorzystałem z random.org do wygenerowania hasełek, które wkleiłem do arkusza:

iRedMail dostarcza skrypty, które przygotowują za nas plik LDIF, który potem musimy wykorzystać do dodania użytkowników za pomocą polecenia ldapadd. Powinny być w folderze instalacyjnym iRedMaila, w folderze tools. Są dwa skrypty: create_mail_user_OpenLDAP.py i create_mail_user_OpenLDAP.sh. Ja skorzystałem z tego pierwszego, bo we wdrożeniu chciałem mieć katalogi użytkowników w konkretnym katalogu, a ten bashowy skrypt chyba na to nie pozwalał.

To, co trzeba sobie w tym skrypcie zmienić to:

# LDAP server address.
LDAP_URI = 'ldap://127.0.0.1:389'

# LDAP base dn.
BASEDN = 'o=domains,dc=example,dc=com'

# Bind dn/password
BINDDN = 'cn=Manager,dc=example,dc=com'
BINDPW = 'supersecretpassword'

# Storage base directory.
STORAGE_BASE_DIRECTORY = '/var/vmail/vmail1'

# Append timestamp in maildir path.
APPEND_TIMESTAMP_IN_MAILDIR = True

# Get base directory and storage node.
std = STORAGE_BASE_DIRECTORY.rstrip('/').split('/')
STORAGE_NODE = std.pop()
STORAGE_BASE = '/'.join(std)

# Hashed maildir: True, False.
# Example:
#   domain: domain.ltd,
#   user:   zhang ([email protected])
#
#       - hashed: d/do/domain.ltd/z/zh/zha/zhang/
#       - normal: domain.ltd/zhang/
HASHED_MAILDIR = True

Te zmienne definiują:

  • LDAP_URI – adres serwera LDAP, do którego się łączymy (jest on na serwerze localnie),
  • BASEDN – DN domeny, każdy element oddziela się przecinkiem w miejscu, gdzie jest kropka w nazwie, np. super.domena.com dzieli się na dc=super,dc=domena,dc=com, dopisujemy na początku o=domains wyjątkowo w tym polu,
  • BINDDN – użytkownik, na prawach którego wykonujemy operację, przy czym Manager jest kontem, które ma pełne prawa do modyfikowania wszystkiego, co jest w LDAPie, w dużym uproszczeniu to jest nazwa użytkownika + nazwa domeny, którą przedstawiałem wyżej, w tym polu trzeba poprawić domenę
  • BINDPW – hasło do konta Manager, znajdziemy je w katalogu instalacyjnym w pliku iRedMail.tips,
  • STORAGE_BASE_DIRECTORY – katalog bazowy, w którym znajdują się wszystkie skrzynki, ścieżka do katalogu użytkownika to STORAGE_BASE_DIRECTORY/<domena>/<folder-użytkownika>
  • APPEND_TIMESTAMP_IN_MAILDIR – jeśli true, foldery użytkownika wyglądają tak: supra-2020.04.22.17.19.56
  • HASHED_MAILDIR – tutaj ładnie jest opisane w skrypcie, w praktyce jak mamy włączony hash z ścieżką katalogu bazowego jak w skrypcie oraz dopisanie daty do nazwy folderu użytkownika to pełna ścieżka do skrzynki mailowej przykładowego użytkownika supra wygląda tak: /var/vmail/vmail1/domain.com/s/u/p/supra-2020.04.22.17.19.56

Jak mamy to, możemy sobie wrzucić plik CSV na serwer i go po prostu zaimportować. Warto sobie sprawdzić czy nazwy wyświetlane dobrze nam się czytają, by nie mieć żadnych znaków z niespodzianką (np. moje imię ma znak, który jest polski):

Jak widać, wszystko działa.

Jak to jest wszystko okej, odpalamy skrypt:

sudo python create_mail_user_OpenLDAP.py /home/supra/import.csv

Z jakiegoś powodu otrzymywałem ten błąd:

Traceback (most recent call last):
  File "create_mail_user_OpenLDAP.py", line 303, in <module>
    ldif_writer.unparse(dn, data)
  File "/usr/lib/python2.7/dist-packages/ldif.py", line 194, in unparse
    dn = dn.encode('utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 11: ordinal not in range(128)

Żeby rozwiązać to, należy wykorzystać program dos2unix, by przekonwertować plik:

$ dos2unix import.csv
dos2unix: konwersja pliku import.csv do formatu uniksowego...

Ewentualnie to można zrobić w Vimie poleceniem :set nobomb i zapisując plik. Teraz wynik dostaję taki:

< INFO > User data are stored in /home/supra/import.csv.ldif, you can verify it before importing it.
< INFO > You can import it with below command:
ldapadd -x -D cn=Manager,dc=example,dc=com -W -f /home/supra/import.csv.ldif

Plik wygląda tak:

dn: [email protected],ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: [email protected]
userPassword: {SSHA}wDV2pLwacxHOT8GpMRL3+wta9PfGGmVp
mailQuota: 5368709120
cn:: UmFkb3PFgmF3IFNlcmJh
sn: supra
uid: supra
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/s/u/p/supra-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/s/u/p/supra-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

dn: [email protected],ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: [email protected]
userPassword: {SSHA}L+5CB3x3tUyilp90aF9FFa9/Rab5FqAo
mailQuota: 5368709120
cn: Marek Marecki
sn: mmarecki
uid: mmarecki
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/m/m/a/mmarecki-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/m/m/a/mmarecki-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

dn: [email protected],ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: [email protected]
userPassword: {SSHA}XL1T9GV1SAqeRrsUx3K0C7eFSsTsm7AT
mailQuota: 5368709120
cn:: RGFyaWEgV2FyecWEc2th
sn: dwarynska
uid: dwarynska
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/d/w/a/dwarynska-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/d/w/a/dwarynska-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

dn: [email protected],ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: [email protected]
userPassword: {SSHA}ObU/Ydy4GUnT1hM3Ebmk+GE4hYPBUlVp
mailQuota: 5368709120
cn: Anna Darecka
sn: adarecka
uid: adarecka
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/a/d/a/adarecka-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/a/d/a/adarecka-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

Taki plik możemy zaimportować do iRedMaila za pomocą polecenia (parametr -w pozwala na podanie hasła w parametrze, -W powoduje, że wpisywane hasło nie jest widziane na ekranie):

ldapadd -x -D cn=Manager,dc=domain,dc=com -f /home/supra/import.csv.ldif -w haslodokontamanagera

W efekcie powinniśmy dostać to:

adding new entry "[email protected],ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "[email protected],ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "[email protected],ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "[email protected],ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "[email protected],ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

Możemy spotkać się z takim błędem:

adding new entry "[email protected],ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"
ldap_add: Already exists (68)

To po prostu oznacza, że dany użytkownik istnieje i jeśli wcześniej mieliśmy jakieś linijki o powodzeniu dodania użytkownika, to musimy usunąć wszystko wyżej wraz z użytkownikiem, który istnieje tak, że pierwszą linią będzie pierwsze pole następnego użytkownika. Każdy wpis jest oddzielony pustą linią i powinniśmy zachować takie odstępy, lecz na początku tego nie trzeba mieć.

Wyszukiwanie użytkowników w LDAPie w konsoli i w GUI

W konsoli jest to proste, wystarczy polecenie ldapsearch:

ldapsearch -b dc=etf2l,dc=site -H ldap://127.0.0.1 -D cn=vmail,dc=etf2l,dc=site -w secretvmailadminpassword -s sub "(&(mailMessageStore=*)(cn=postmaster))"

Parametry to:

  • -b – domena, dla której wykonujemy zapytanie
  • -H – host, do którego wysyłamy zapytanie
  • -D – konto, które ma prawa do wykonania tego typu zapytań w postaci DN
  • -w – hasło do tego konta
  • -s – nasze zapytanie

Zapytanie wyżej wyświetla daje w wyniku konta, które mają dowolną wartość wpisaną w atrybucie mailMessageStore (ścieżka do skrzynki pocztowej użytkownika) oraz wartość postmaster wpisaną w atrybucie cn (common name, z reguły jest unikalne). Poniżej zapytanie, które pyta tylko o konta z cn o wartości postmaster:

ldapsearch -b dc=etf2l,dc=site -H ldap://127.0.0.1 -D cn=vmail,dc=etf2l,dc=site -w secretvmailadminpassword -s sub "(cn=postmaster)"

Jeśli chodzi o GUI to tutaj trzeba trochę pokombinować. Widziałem komentarze na forach odradzające korzystania z phpLDAPadmin, więc skorzystałem z LAM (LDAP Account Manager).

Na początku ściągamy pakiet na naszą dystrybucję, w moim przypadku nie było w repozytorium, więc ściągnąłem sobie plik .deb z sieci i go zainstalowałem:

wget https://netix.dl.sourceforge.net/project/lam/LAM/7.2/ldap-account-manager_7.2-1_all.deb
sudo dpkg -i ldap-account-manager_7.2-1_all.deb
sudo apt -f install -y

W ten sposób LAM będzie zainstalowany. Następnie musimy go wystawić poprzez stronę i to ułatwia LAM samo w sobie, bo w /etc/ldap-account-manager/nginx.conf znajdziemy szablon lokalizacji, który możemy dodać do strony:

location /lam {
        index index.html;
        alias /usr/share/ldap-account-manager;
        autoindex off;

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $request_filename;
        }

        location ~ /lam/(tmp/internal|sess|config|lib|help|locale) {
                deny all;
                return 403;
        }

}

Trzeba tutaj poprawić linijkę, którą zaznaczyłem, bo pewnie nie używacie już takiej wersji PHP (OBY!). W domyślnej konfiguracji PHP aktualnej wersji pracuje pod adresem 127.0.0.1:9999, więc ta linijka powinna mieć fastcgi_pass 127.0.0.1:9999;. Ponadto dodałbym w tej lokalizacji takie dwie linijki, by ograniczyć dostęp do tej przeglądarki tylko z sieci, w której mamy możliwość administrowania wszystkim (w przykładzie będzie 192.168.10.0/24). Na lenia wrzuciłem konfigurację do /etc/nginx/sites-available/00-default-ssl.conf i dzięki temu dostanę się do strony wpisując w przeglądarce adres https://mail.domain.com/lam:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name mail.domain.com;

location /lam {
        allow 192.168.10.0/24;
        deny all;
        index index.html;
        alias /usr/share/ldap-account-manager;
        autoindex off;
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass 127.0.0.1:9999;
                fastcgi_param SCRIPT_FILENAME $request_filename;
        }

        location ~ /lam/(tmp/internal|sess|config|lib|help|locale) {
                deny all;
                return 403;
        }

}
    root /var/www/html;
    index index.php index.html;
    include /etc/nginx/templates/misc.tmpl;
    include /etc/nginx/templates/ssl.tmpl;
    include /etc/nginx/templates/iredadmin.tmpl;
    include /etc/nginx/templates/roundcube.tmpl;
    include /etc/nginx/templates/sogo.tmpl;
    include /etc/nginx/templates/netdata.tmpl;
    include /etc/nginx/templates/php-catchall.tmpl;
    include /etc/nginx/templates/stub_status.tmpl;
}

Po otwarciu strony musimy nieco zmienić konfigurację pod kątem logowania:

Następnie wybieramy Edytuj profile serwerowe:

W tym polu wpisujemy hasło lam i warto je zmienić:

W Ustawieniach głównych, sekcji Server settings ustawiamy odpowiedni DN domeny, do której się łączymy, przy okazji można zmienić język i strefę czasową:

Dodatkowo w Ustawieniach bezpieczeństwa definiujemy w polu Lista uprawnionych użytkowników definiujemy DN konta Manager:

Na końcu hasło do profilu warto sobie zmienić po to, by nikt nam tego profilu nie zmieniał:

Następnie możemy się zalogować wklejając hasło do konta Manager:

Ponadto warto sobie przejść do karty Typy kont i zmienić ustawienia Aktywuj rodzaje kont. Na tym etapie dałem sobie spokój z ukrywaniem mojej domeny, bo i tak do strony dostęp jest zablokowany:

W polach wpisałem:

  • Użytkownicy:
    • Sufiks LDAP: ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
    • Atrybuty listy: (to było za długie, by wpisać w liście)
uid;#cn;#accountStatus;#amavisLocal;#enabledService;#homeDirectory;#mail;#mailMessageStore;#mailQuota;#memberOfGroup;#objectClass;#shadowLastChange;#sn;#storageBaseDirectory;#userPassword
  • Grupy:
    • Sufiks LDAP: ou=Groups,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
    • Atrybuty listy: cn;#accountStatus;#enabledService;#mail;#mail;#objectClass

Po zmianach zapisujemy i logujemy się do konta Manager:

W ten sposób otrzymujemy ładną przeglądarkę kont:

Może nie tak ładną, wszystko przez pole enabledservice.

Tak czy siak mi lepiej się tego interfejsu używa poprzez Widok drzewa, który można znaleźć u góry, po prawej. W aktualnym interfejsie jest lepiej wyszukać coś, ale w tym drzewku łatwiej modyfikować i dodawać.

Dodajemy atrybuty poprzez pole Dodaj nowy atrybut po prawej stronie, następnie wybieramy z listy atrybut, który nas interesuje:

Potem jedynie wpisujemy, co chcemy i zapisujemy (przycisk jest na samym dole, Zaktualizuj obiekt). Tutaj przykład jeśli chcielibyśmy dodać użytkownikowi grupę po to, by po wysłaniu maila przez jakiegoś użytkownika na [email protected] otrzymywał wiadomości (inaczej mówiąc dodajemy użytkownika do wewnętrznej listy mailingowej):

Dodawanie aliasów

Na starym serwerze aliasy były przechowywane w pliku /etc/aliases, którego format był następujący:

suprovsky: supra
a.darecka: adarecka
ad: adarecka
admin: supra, adarecka

Po lewej znajduje się alias, po dwukropku znajduje się lista użytkowników, którzy mają otrzymywać wiadomości po odebraniu przez serwer wiadomości na alias, czyli np. wysyłka maila na [email protected] powoduje wysłanie maili do [email protected] oraz [email protected].

W przypadku iRedMaila z OpenLDAP są dwie opcje, by to sobie dodać taki alias: przez LAM i przez polecenie ldapmodify z przygotowanym plikiem LDIF. W przypadku LAMa wystarczy, że dodamy nowy atrybut o nazwie shadowaddress i podamy po prostu pełny adres aliasu, czyli np. dla konta supra wartości atrybutu to [email protected] oraz [email protected].

Postać LDIF dla supra i adarecka wyglądałby następująco (trzeba pamiętać o dodaniu pustej linii pomiędzy wpisami):

dn: [email protected],ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
add: shadowaddress
shadowaddress: [email protected]
shadowaddress: [email protected]

dn: [email protected],ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
add: shadowaddress
shadowaddress: [email protected]
shadowaddress: [email protected]

Taki przygotowany LDIF zapisujemy do pliku, dajmy na to aliases.ldif i wrzucamy do LDAPa poleceniem:

ldapmodify -H ldap://127.0.0.1 -D cn=Manager,dc=etf2l,dc=site -f aliases.ldif -w 0PjBPdKWNgs3dWfux8BTK16wc6XCBF

W wyniku dostałem:

modifying entry "[email protected],ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site"

modifying entry "[email protected],ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site"

Czyli wszystko cacy.

Dodawanie grup (list mailingowych)

To akurat jest dosyć upierdliwe, bo jeśli chcemy dodać 1 grupę 500 użytkownikom to póki co nie znalazłem na to jakiejś magicznej sztuczki.

Ogólnie grupę tworzy się takim LDIFem (można go znaleźć tutaj):

dn: [email protected],ou=Groups,domainName=mydomain.com,o=domains,dc=etf2l,dc=site
accountStatus: active
cn: demolist
enabledService: mail
enabledService: deliver
enabledService: displayedInGlobalAddressBook
mail: [email protected]
objectClass: mailList
accesspolicy: domain

W tym LDIFie warto zwrócić uwagę na accesspolicy i poczytać w linku, który podałem wyżej. Wartość domain powoduje, że można na taką grupę wysyłać maile tylko z tej samej domeny. Dodajemy go tak:

ldapadd -x -D cn=Manager,dc=domain,dc=com -f /home/supra/newgroup.ldif -w haslodokontamanagera

Potem musimy do każdego obiektu, który ma należeć do wybranej grupy mailingowej (w tym przypadku [email protected]) dodać atrybut z adresem mailowym takiej listy. Tutaj LDIF wygląda tak:

dn: [email protected],ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
add: memberOfGroup
memberOfGroup: [email protected]

I tutaj tak samo zmiany wprowadzamy poleceniem:

ldapmodify -H ldap://127.0.0.1 -D cn=Manager,dc=etf2l,dc=site -f addtogroup.ldif -w 0PjBPdKWNgs3dWfux8BTK16wc6XCBF

Modyfikowanie istniejących wpisów w LDAPie

To też sobie zapisałem, bo przydało mi się. ldapmodify można też używać w trybie interaktywnym, gdy się nie poda w argumencie -f pliku LDIF. Wtedy dane z w takim formacie podaje się wpisując je ręcznie i oddzielając enterami. Po wpisaniu całego wpisu należy zrobić linijkę przerwy i wykonać skrót Ctrl+D. To spowoduje wyjście z trybu interaktywnego i wykonanie zapytania do LDAPa. Przykład:

ldapmodify -H ldap://127.0.0.1 -D cn=Manager,dc=etf2l,dc=site -w 0PjBPdKWNgs3dWfux8BTK16wc6XCBF

Następnie dane, które wpisałem:

dn: [email protected],ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
replace: memberOfGroup
memberOfGroup: [email protected]

W ten sposób z poprzednio ustawionego pola memberOfGroup na [email protected] użytkownik supra będzie miał ustawioną grupę [email protected].

Usunięcie domeny z pola logowania dla iRedMail (konkretnie SOGo)

Jest to tutaj opisane, ale nie dla SOGo. Do tego się odniosę. Trzeba edytować 1 plik, mianowicie /etc/sogo/sogo.conf, lecz przed tym trzeba sobie umożliwić jego modyfikację:

sudo chmod o+w /etc/sogo/sogo.conf

W pliku modyfikuję takie pola (podaję wartości, które ustawiam, nie wszystko dotyczy samego usunięcia z domeny, bo część to po prostu dobre praktyki):

SOGoLanguage = Polish;
SOGoForceExternalLoginWithEmail = NO;
SOGoTimeZone = "Europe/Warsaw";
SOGoUserSources = (
///zmieniamy tylko te pola///
bindDN = "cn=vmail,dc=etf2l,dc=site"; //usunąłem 'o=domains,' stąd
bindFields = (uid); //domyślna wartość to mail
)

Po zmianach restartujemy usługę poleceniem systemctl restart sogo i sprawa załatwiona.

Autokonfiguracja klientów pocztowych

Zbawienie dla administratorów. Wpisujesz nazwę użytkownika, maila i hasło. To wszystko. Brzmi zbyt pięknie, by było prawdziwe? Niekoniecznie musi! Są 2 gotowe formatki, które można wykorzystać i one są dla Microsoft Outlook oraz Mozilla Thunderbird. Sytuacja jest prosta: należy ustawić odpowiednie wpisy w DNSie i wystawić pliki na serwerze WWW.

Tutaj można zauważyć 2 wpisy CNAME autoconfig i autodiscover kierujące połączenia na domenę mail.etf2l.site, która jest innym CNAME, który kieruje na etf2l.site, a ten już kieruje na odpowiedni adres IP (to jest wpis A). To będzie nam potrzebne. Te dwa CNAME mają po prostu wskazywać serwer, na którym są formatki, które ma pobierać klient pocztowy. W dodatku nie musi być to bezpośrednio nasz serwer mailowy, ale zrobiłem tak, bo tak po prostu mi było łatwiej. Ponadto powinniśmy mieć wpis SRV _autodiscover._tcp, który kieruje na adres serwera, na którym jest taka formatka. W wartości powinniśmy wpisać 0 1 443 mail.etf2l.site, przy czym zmieniamy adres naszego serwera formatki na właściwy.

Wyjaśnimy sobie po co są te domeny. Domena autodiscover.etf2l.site (konkretnie adres https://autodiscover.etf2l.site/autodiscover/autodiscover.xml jest wykorzystywna przez Outlooka do wykrycia konfiguracji poczty. W sumie to nie musimy mieć nawet do tego subdomeny, bo na dobrą sprawę moglibyśmy wystawiać to na domenie etf2l.site bezpośrednio – to jest kwestia czysto seperacji konfiguracji. Strona autoconfig.etf2l.site jest zaś dla Thunderbirda – on łączy się na adres https://autoconfig.etf2l.site/mail/config-v1.1.xml i z niego zaciąga sobie konfigurację. Tutaj subdomena akurat jest potrzebna.

Outlook widząc domenę etf2l.site sprawdza wpis SRV, o którym wspomniałem by sprawdzić pod jakim adresem jest plik konfiguracyjny, następnie wysyła na adres wspomniany wyżej w POST taką zawartość:

 <?xml version="1.0" encoding="utf-8"?> 
 <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"> 
 <Request>
 <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema> 
 <EMailAddress>[email protected]</EMailAddress> 
 </Request> 
</Autodiscover>

Jak można zauważyć, w polu EMailAddress jest adres użytkownika, który próbuje sobie skongurować Outlooka. Dla Outlooka nie wystawiamy autodiscover.xml w postaci gołego XMLa – możemy do tego wykorzystać skrypt w PHP, który wpisuje nam adres mailowy użytkownika w XML, a następnie nam go zwraca (musimy ten XML edytować podając prawidłowe dane do naszego serwera pocztowego):

<?php
//get raw POST data so we can extract the email address
$data = file_get_contents("php://input");
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);

//set Content-Type
header("Content-Type: application/xml");
?>
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>

<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>IMAP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>993</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
            </Protocol>
            <Protocol>
                <Type>POP3</Type>
                <Server>mail.etf2l.site</Server>
                <Port>995</Port>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
                <?php echo $LoginName; ?>
            </Protocol>
            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>465</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>

Warto wziąć pod uwagę, że jako SMTP określiłem połączenie SSL/TLS na porcie 465 – w większości użytkownicy będą woleli korzystać ze STARTTLS na porcie 587. Korzystałem z 465 w ramach testu, bo UPC nie blokuje tego portu 😂

W praktyce ze STARTTLSem na 587 powinniśmy podmienić w ten sposób sekcję Protocol:

            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>587</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <Encryption>TLS</Encryption>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>

W naszym przykładzie będziemy przechowywać te formatki w katalogu /var/www/autodiscover (może być to dowolna inna lokalizacja, po prostu przyjęło się, że w /var/www z reguły są pliki wystawiane przez serwer HTTP). Ten plik będzie nazwany jako autodiscover.php. Do tego config, który jest potrzebny dla nginxa, by wystawiał dostęp dla tej domeny i do tego pliku (umieściłem go w /etc/nginx/sites-available/autodiscover.etf2l.site:

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name autodiscover.etf2l.site;
    root /var/www/autodiscover;
    index index.php;
        include /etc/nginx/templates/ssl.tmpl;
        error_log /var/log/nginx/autodiscover-error.log;
        access_log /var/log/nginx/autodiscover-access.log combined;
        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
    location ~ /(?:a|A)utodiscover/(?:a|A)utodiscover.xml {
        root /var/www/;
        try_files /autodiscover/autodiscover.php =404;
        fastcgi_pass 127.0.0.1:9999; #w tym miejscu jest prawidłowa wartość dla serwera z iredmailem
        fastcgi_index  index.php;
        include        fastcgi.conf;
        fastcgi_param SERVER_ADDR "";
        fastcgi_param REMOTE_ADDR $http_x_real_ip;
    }
}

Następnie należy dodać sobie symlink takiego configa do /etc/nginx/sites-enabled, by był wykorzystywany przez nginxa i warto też wykonać test konfiguracji, by sprawdzić, czy nie wkradł nam się do configa jakiś błąd przed restartem usługi. Jeśli taki będzie i zrestartujemy usługę, ta się nie uruchomi po zatrzymianiu i to może dla nas być problem. Test wykonuje się poleceniem nginx -t. Taki jest poprawny wynik testu:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Koniec końców linkuję konfig, wykonuję test i restartuję usługę tak:

cd /etc/nginx/sites-enabled
ln -s ../sites-available/autodiscover.etf2l.site
nginx -t
systemctl restart nginx

Następnie możemy sobie przetestować, czy taka formatka nam działa wykonując ręczny test za pomocą cURLa. Musimy zapisać sobie wspomniany na początku request do pliku. Nazwijmy go req.xml, następnie wykonujemy następujące polecenie:

curl -X POST file:/home/supra/req.xml https://autodiscover.etf2l.site/autodiscover/autodiscover.xml

W wyniku otrzymałem:

<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  <Request>
    <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
    <EMailAddress>[email protected]</EMailAddress>
  </Request>
</Autodiscover>
<?xml version="1.0" encoding="utf-8" ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>IMAP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>993</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName></LoginName>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
            </Protocol>
            <Protocol>
                <Type>POP3</Type>
                <Server>mail.etf2l.site</Server>
                <Port>995</Port>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
                            </Protocol>
            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>465</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName></LoginName>
                <SPA>off</SPA>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>

To oznacza, że wszystko się zgadza. Z poziomu Outlooka wygląda to tak:

W przypadku Thunderbirda jest podobnie, lecz nie trzeba robić sztuczek z PHPem – wystarczy w odpowiedni sposób przygotować plik XML (umieszczając go w /var/www/autodiscover) oraz umieścić do niego pasujący plik konfiguracyjny do nginxa (oczywiście na Apache’u też to można zrobić, ale dla mnie Apache śmierdzi i nie będę go używał):

<?xml version="1.0" encoding="UTF-8"?>

<clientConfig version="1.1">
    <emailProvider id="etf2l.site">
        <domain>mail.etf2l.site</domain>
        <displayName>Mail</displayName>
        <displayShortName>Mail</displayShortName>
        <incomingServer type="imap">
            <hostname>mail.etf2l.site</hostname>
            <port>993</port>
            <socketType>SSL</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </incomingServer>
        <incomingServer type="imap">
            <hostname>mail.etf2l.site</hostname>
            <port>143</port>
            <socketType>STARTTLS</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </incomingServer>
        <outgoingServer type="smtp">
            <hostname>mail.etf2l.site</hostname>
            <port>465</port>
            <socketType>SSL</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </outgoingServer>
        <outgoingServer type="smtp">
            <hostname>mail.etf2l.site</hostname>
            <port>587</port>
            <socketType>STARTTLS</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </outgoingServer>
    </emailProvider>
</clientConfig>

W tym XMLu kolejność protokołów ma znaczenie, wiec jeśli chcemy w pierwszej kolejności używać portu 587 zamiast 465 to musimy zamienić sekcje outgoingServer miejscami. Następnie config do nginxa wygląda tak:

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name autoconfig.etf2l.site;
        location ^~ /mail {
        alias /var/www/autodiscover;
        try_files $uri =404;
}
    root /var/www/autodiscover;
    index index.php;
        include /etc/nginx/templates/ssl.tmpl;
        error_log /var/log/nginx/autodiscover-error.log;
        access_log /var/log/nginx/autodiscover-access.log combined;

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
}

Po zrobieniu symlinka do tego configa w /etc/nginx/sites-enabled, zrobieniu testu i zrestartowaniu nginxa możemy zobaczyć jak nasz Thunderbird się sam konfiguruje:

Jest też opcja, by móc automatycznie konfigurować sprzęt Apple’a, ale jestem zbyt leniwy, by to przetestować. Jest to opisane tutaj.

Zabezpieczenie się przed niepowołanym dostępem do administracji

Jest kilka rzeczy, które powinno się zrobić z mojego punktu widzenia, by zminimalizować ryzyko, że ktoś niepowołany wejdzie na jakąś stronę. Po pierwsze, należy obciąć dostęp do LDAP Account Managera/phpLDAPadmin (jeśli zainstalowany) w nginxie, następnie to należy powtórzyć dla lokalizacji w plikach:

  • /etc/nginx/templates/adminer.tmpl,
  • /etc/nginx/templates/iredadmin.tmpl,
  • /etc/nginx/templates/iredadmin.tmpl-subdomain.tmpl,
  • /etc/nginx/templates/netdata.tmpl,
  • /etc/nginx/templates/netdata-subdomain.tmpl.

Przykład w /etc/nginx/templates/iredadmin.tmpl:

# Settings for iRedAdmin.

# static files under /iredadmin/static
location ~ ^/iredadmin/static/(.*) {
    alias /opt/www/iredadmin/static/$1;
}

# Python scripts
location ~ ^/iredadmin(.*) {
    allow 192.168.10.0/24;
    deny all;
    rewrite ^/iredadmin(/.*)$ $1 break;

    include /etc/nginx/templates/hsts.tmpl;

    include uwsgi_params;
    uwsgi_pass 127.0.0.1:7791;
    uwsgi_param UWSGI_CHDIR /opt/www/iredadmin;
    uwsgi_param UWSGI_SCRIPT iredadmin;
    uwsgi_param SCRIPT_NAME /iredadmin;

    # Access control
    #allow 127.0.0.1;
    #allow 192.168.1.10;
    #allow 192.168.1.0/24;
    #deny all;
}

# iRedAdmin: redirect /iredadmin to /iredadmin/
location = /iredadmin {
    rewrite ^ /iredadmin/;
}

# Handle newsletter-style subscription/unsubscription supported in iRedAdmin-Pro.
location ~ ^/newsletter/ {
    rewrite /newsletter/(.*) /iredadmin/newsletter/$1 last;

Po zmianach wiadomo, restarcik nginxa się przyda: systemctl restart nginx.

Poza tym powinno się nasłuchiwać połączenia serwera SSH tylko i wyłącznie z podsieci administracyjnej, powinno się wyłączyć logowanie na roota po SSH oraz wyłączyć logowanie za pomocą haseł i przerzucić się na klucze publiczne zmieniając plik /etc/ssh/sshd_config (zamieszczam tylko istotny fragment):

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
PermitRootLogin no
PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no

Dostęp z innych podsieci możemy załatwić za pomocą iptables:

iptables -A INPUT -p tcp --dport 22 --source 192.168.10.0/24 -j ACCEPT

Warto też się upewnić, że domyślna polityka INPUT dla iptables to DROP (to oznacza, że dla każdego ruchu niezdefiniowanego w regułach iptables w sekcji INPUT jest wykonywany DROP, czyli brak odpowiedzi):

sudo iptables -L -v
[sudo] password for supra:
Chain INPUT (policy DROP 1803K packets, 167M bytes)

Do iptables warto mieć opcję zapisywania konfiguracji i można znaleźć o tym fajny poradnik tutaj.