顯示具有 tls 標籤的文章。 顯示所有文章
顯示具有 tls 標籤的文章。 顯示所有文章

2024年11月19日 星期二

Linux 開發筆記 - OpenLDAP StartTLS 憑證驗證與故障排除 @ Ubuntu 20.04


負責 DevOps 同事休假,當初 LDAP 架設沒涉入,用 AI 輔助來練一下功,盡量讓同事好好休假不用 oncall 解題,就把這過程筆記一下。

現在有 AI 輔助服務,做事的心態變了不少,包括:
  1. 面對不是自己從頭到尾參與的計劃時,該怎樣建立自己了解系統思維或是達成想做的任務
  2. AI 的答案也不一定是對的,該如何驗證(如同管理或跨團隊合作上,請夥伴做事,但不一定做對,該怎樣驗正)
事件起因是一些小型內部服務,因 LDAP 憑證失效而無法完成登入(已登入不受影響),我的追法:
  1. 請 AI 給我指令或程式,檢驗快速檢驗 ldap 連線過程,著重在憑證檢查,例如檢查 https 憑證最常就是靠 openssl 指令或是 browser 瀏覽檢視憑證
  2. 有時 AI 會回的很搞剛,開始回寫 code 的 python 解法,這時因為自己有經驗 openssl 指令就能搞定,所以不斷提醒 AI 直接給指令解
  3. 對於 OpenLDAP 不熟的我,開始追問 AI 憑證相關的方向,才順勢了解 StartTLS ,才知道有 ldapsearch, slaptest 指令可用
  4. 對於管理線上服務踩過雷,知道不能隨便 service restart,多問一下 AI 該怎樣先檢驗設定檔,避免機器從 running -> stop -> 設定有誤 -> 服務停止營運
使用 openssl 指令檢查 SSL 憑證,假設網域是 ldap-dmz.changyy.org

```
$ openssl s_client -connect ldap-dmz.changyy.org:443 
...
---
SSL handshake has read xxxx bytes and written xxx bytes
Verification: OK
---
...
```

使用 openssl 指令檢查 LDAP + StartTLS 憑證,假設網域是 ldap-dmz.changyy.org

```
$ openssl s_client -connect ldap-dmz.changyy.org:389 -starttls ldap
...
---
SSL handshake has read xxxx bytes and written xxx bytes
Verification error: certificate has expired
---
...
```

得知 LDAP + StartTLS 使用流程中的憑證過期了,且此例剛好 https 憑證已正常工作,僅 LDAP + StartTLS 的部分失敗,所以很輕鬆的可以把 https 憑證複製一份到 ldap 使用即可。先追蹤設定檔位置:

```
$ sudo cat /etc/ldap/slapd.d/cn\=config.ldif | grep -i TLS
olcTLSCACertificateFile: /etc/ssl/ldap/wildcard.*.ca-bundle
olcTLSCertificateFile: /etc/ssl/ldap/wildcard.*.crt
olcTLSCertificateKeyFile: /etc/ssl/ldap/wildcard.*.key
$ sudo tree -L 1 /etc/ssl/
/etc/ssl/
├── certs
├── ldap
├── nginx
├── openssl.cnf
└── private
```

速速解:

```
$ sudo cp -r /etc/ssl/ldap /etc/ssl/ldap-bak
$ sudo cp /etc/ssl/nginx/wildcard.* /etc/ssl/ldap/
```

檢驗設定檔和重啟服務:

```
$ sudo slaptest
config file testing succeeded
$ sudo service slapd restart
```

再次驗證:

```
$ openssl s_client -connect ldap-dmz.changyy.org:389 -starttls ldap
...
---
SSL handshake has read xxxx bytes and written xxx bytes
Verification: OK
---
...
```

此外,追蹤 LDAP 和使用他的服務時,意外發現不同的服務整合過程,也順手筆記一下,例如 Apache2 設定檔:

僅 LDAP 非加密:

<Location />
    Order allow,deny
    Allow from all
    AuthType basic
    AuthName "service.changyy.org"
    AuthBasicProvider ldap
    AuthLDAPUrl "ldap://ldap-dmz.changyy.org/dc=changyy,dc=org?uid"
    Require valid-user
</Location>

LDAP + StartTLS:

<Location />
    Order allow,deny
    Allow from all
    AuthType basic
    AuthName "service.changyy.org"
    AuthBasicProvider ldap
    AuthLDAPUrl "ldap://ldap-dmz.changyy.org/dc=changyy,dc=org?uid" TLS
    Require valid-user
</Location>

對應的其他服務也會有類似架構,舉例來說 Mantis 也有 mantisbt.org/docs/master/en-US/Admin_Guide/html/admin.config.auth.ldap.html

預設是啟用 LDAP + StartTLS

//
// Determines whether the connection will attempt an opportunistic upgrade to a TLS connection (STARTTLS).
//
// Defaults to ON.
//
// $g_ldap_use_starttls = ON

需要測試 LDAP 健康情況時,可以把它關閉

// $g_ldap_use_starttls = OFF

補充檢查 ldap service 健康情況時,最常是直接使用 ldapsearch 指令:

```
$ sudo apt install ldap-utils
$ ldapsearch -x -H 'ldap://ldap-dmz.changyy.org' -b 'dc=changyy,dc=org'
...
# search result
search: #
result: 0 Success
...
# numResponses: ###
# numEntries: ###
```

測試 LDAP + StartTLS:

```
$ ldapsearch -x -H 'ldap://ldap-dmz.changyy.org' -b 'dc=changyy,dc=org' -Z
...
ldap_start_tls: Connect error (-11)
additional info: (unknown error code)
ldap_result: Can't contact LDAP server (-1)
```

測試 LDAP + StartTLS 需要更多 debug 資訊:

```
$ ldapsearch -x -H 'ldap://ldap-dmz.changyy.org' -b 'dc=changyy,dc=org' -Z -d 1
...
TLS: peer cert untrusted or revoked (0x402)
TLS: can't connect: (unknown error code).
...
ldap_start_tls: Connect error (-11)
...
```

用 PHP Code 嘗試建立連線,先確認 php.ini 套件:

```
php -i | grep ldap
/etc/php/7.4/cli/conf.d/20-ldap.ini,
Protocols => dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtmp, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
ldap
...
```

運行:

```
$ cat /tmp/t.php 
<?php
$ldapconn = ldap_connect("ldap://ldap-dmz.changyy.org");
if ($ldapconn) {
    ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
    // 關閉 TLS
    putenv('LDAPTLS_REQCERT=never');
    
    $bind = ldap_bind($ldapconn);
    if ($bind) {
        echo "LDAP bind successful...\n";
    } else {
        echo "LDAP bind failed...\n";
    }
}
$ php /tmp/t.php 
LDAP bind successful...
```

收工!

2020年2月19日 星期三

[Linux] 在 Ubuntu 重編 git 處理 error: gnutls_handshake() failed: A TLS fatal alert has been received @ Ubuntu 12.04

當使用 git clone https:// 來源時,會出現以下錯誤訊息:

error: gnutls_handshake() failed: A TLS fatal alert has been received. while accessing https://service/project.git/info/refs
fatal: HTTP request failed

解法就是重編 git (細節似乎是 gnutls 問題)

流程:
  1. 到 https://github.com/git/git/releases 下載 git 程式碼(此例用 v2.25.1)
  2. 安裝 libcurl4-openssl-dev libexpat1-dev 等編譯環境
  3. 編他:./configure --with-expat --with-curl --with-openssl
連續動作:

$ dpkg -l | grep gnutls
ii  libcurl3-gnutls                             7.22.0-3ubuntu4.17                      Multi-protocol file transfer library (GnuTLS)
ii  libgnutls-dev                               2.12.14-5ubuntu3.14                     GNU TLS library - development files
ii  libgnutls-openssl27                         2.12.14-5ubuntu3.14                     GNU TLS library - OpenSSL wrapper
ii  libgnutls26                                 2.12.14-5ubuntu3.14                     GNU TLS library - runtime library
ii  libgnutls26:i386                            2.12.14-5ubuntu3.14                     GNU TLS library - runtime library
ii  libgnutlsxx27                               2.12.14-5ubuntu3.14                     GNU TLS library - C++ runtime library
ii  libneon27-gnutls                            0.29.6-1ubuntu1                         HTTP and WebDAV client library (GnuTLS enabled)
$ sudo apt-get install libcurl4-openssl-dev tcl-dev libexpat1-dev
$ wget https://github.com/git/git/archive/v2.25.1.tar.gz
$ tar -xvf v2.25.1.tar.gz && cd git-v2.25.1
$ make configure
$ ./configure --with-expat --with-curl --with-openssl
$ make test
$ sudo make install


其中 make test 會跑一陣子,可以選擇執行 XD

2019年9月11日 星期三

[macOS] 修正 Python 錯誤訊息 (caused by URLError(SSLError(1, u'[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590)'),))

查了一下,就是 openssl 版本不夠新。一開始還以為是自己用 MacPorts 維護,導致不是用系統 Python 的關係,但在追細一點就可以知道單純更新 openssl 就搞定了。

$ python -V
Python 2.7.16
$ /usr/bin/python -V
Python 2.7.10
$ /usr/bin/python -c "import json, urllib2; print json.load(urllib2.urlopen('https://www.howsmyssl.com/a/check'))['tls_version']"
TLS 1.2
$ python -c "import json, urllib2; print json.load(urllib2.urlopen('https://www.howsmyssl.com/a/check'))['tls_version']"
TLS 1.2

$ openssl version -a
OpenSSL 1.0.2s  28 May 2019
built on: reproducible build, date unspecified
platform: darwin64-x86_64-cc
options:  bn(64,64) rc4(ptr,int) des(idx,cisc,16,int) idea(int) blowfish(idx)
compiler: /usr/bin/clang -I. -I.. -I../include  -fPIC -fno-common -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -arch x86_64 -O3 -DL_ENDIAN -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
OPENSSLDIR: "/opt/local/etc/openssl"


就好好把 openssl 更新即可修正。感謝佛心 www.howsmyssl.com 測試服務:https://www.howsmyssl.com/

另外也可以直接拿 openssl 上場問問 Google server:

$ openssl s_client -connect google.com:443 -tls1_2

若自己的 openssl 不支援 TLS 1.2 時,會直接回應 unknown option -tls1_2

2016年1月14日 星期四

[Perl] 測試及修正 Perl 5.10.0 的 Email:Send 支援 SMTP + TLS + AUTH 寄信方式 @ perlbrew 5.10.0 / Ubuntu 14.04

上次一摸 Perl 有點久了 Orz 這個問題主要是發生在舊版 Bugzilla 3.0.5 on Perl 5.10.0 環境上,想要走 SMTP + TLS + AUTH 的寄信方式,只是核心部分抽出來驗證後,只須如此就能打造測試環境了:

$ sudo apt-get install perlbrew libssl-dev
$ perlbrew init
$ perlbrew --notest install 5.10.0
$ perlbrew user 5.10.0
bash-4.3$ perl -v

This is perl, v5.10.0 built for x86_64-linux

Copyright 1987-2007, Larry Wall

bash-4.3$ perl -MCPAN -e "CPAN::Shell->notest('install', 'TimeDate')"
bash-4.3$ perl -MCPAN -e "CPAN::Shell->notest('install', 'Date::Format')"
bash-4.3$ perl -MCPAN -e "CPAN::Shell->notest('install', 'Email::Address')"
bash-4.3$ perl -MCPAN -e "CPAN::Shell->notest('install', 'Email::MIME')"
bash-4.3$ perl -MCPAN -e "CPAN::Shell->notest('install', 'Email::Send')"
bash-4.3$ perl -MCPAN -e "CPAN::Shell->notest('install', 'Net::SMTP::TLS')"


如此一來,就可以寫簡單的 Perl 程式測試寄信,此例是處理騰訊企業郵箱的寄信方式:

bash-4.3$ vim send.pl
#!/usr/bin/perl

# http://search.cpan.org/dist/Email-Send/lib/Email/Send.pm
use Date::Format qw(time2str);
use Encode::MIME::Header;
use Email::Address;
use Email::MIME;
use Email::MIME::Modifier;
use Email::Send;
use MIME::Base64;

push @args,
        #Host  => 'hwsmtp.exmail.qq.com:465',
        #Host  => 'smtp.exmail.qq.com:465',
        #Host  => 'smtp.exmail.qq.com:587',
        #Host  => 'smtp.exmail.qq.com',
        Host  => 'hwsmtp.exmail.qq.com',
        username => 'account@my.domainname',
        password => 'password_for_account',
        Hello => 'localhost',
        #ssl => 1,
        tls => 1,
        Debug => 1;

$body = "Hello World";
$method = 'SMTP';
$from = 'account@my.domainname';
$to = 'account@my.domainname';
$subject = "Test Mail";

my $email = ref($msg) ? $msg : Email::MIME->new($body);
$email->header_set('MIME-Version', '1.0') if !$email->header('MIME-Version');
$email->header_set('From', $from);
$email->header_set('To', $to);
$email->header_set('Date', time2str("%a, %e %b %Y %T %z", time()));
$email->header_set('Subject', $subject);
foreach my $part ($email->parts) {
        $part->charset_set('UTF-8');
        #$part->encoding_set('quoted-printable') if !is_7bit_clean($part->body);
}

my $mailer = Email::Send->new({ mailer => $method, mailer_args => \@args });
my $retval = $mailer->send($email);

print $retval;


執行看看:

bash-4.3$ perl send.pl
invalid SSL_version specified at /home/ubuntu/perl5/perlbrew/perls/perl-5.10.0/lib/site_perl/5.10.0/IO/Socket/SSL.pm line 568


人工修正:

bash-4.3$ vim /home/ubuntu/perl5/perlbrew/perls/perl-5.10.0/lib/site_perl/5.10.0/IO/Socket/SSL.pm
將 2210行註解舊的,並更新成新的 Regular Expressiong
#m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1(?:_?[12])?))$}i
m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1[12]?))}i


再次執行:

bash-4.3$ perl test/send.pl
Message sent


因此,這只是單純 Perl 5.10.0 的 SSL.pm 的 TLS 規則影響,造成使用騰訊企業郵箱時,透過 SMTP + TLS + AUTH 寄信時無法成功。而這篇的目的只是記錄透過 Perl Email::Send 寄信走認證的筆記 XD 另外, Email::Send 走 SSL + AUTH 一直沒成功過 Orz

2014年3月31日 星期一

[Linux] 架設 Proftp 與 FTP over TLS 供網頁工讀生上傳資料 @ Ubuntu 12.04

突然收到個命令,要架一檯機器給工讀生用 Orz 雖然幾乎都用 sftp 了,為了讓不熟 Unix 的網頁開發者可以輕鬆上傳資料,最後就是架一台機器,開個 ftp 讓他連進去使用。

流程:

$ sudo apt-get install nginx proftpd
$ sudo vim /etc/proftpd/proftpd.conf
Include /etc/proftpd/tls.conf

$ sudo vim /etc/proftpd/tls.conf
TLSEngine                               on
TLSLog                                  /var/log/proftpd/tls.log
TLSProtocol                             SSLv23
TLSRSACertificateFile                   /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile                /etc/ssl/private/proftpd.key

$ sudo openssl req -x509 -newkey rsa:1024 -keyout /etc/ssl/private/proftpd.key -out /etc/ssl/certs/proftpd.crt -nodes -days 3650

$ sudo vim /etc/proftpd/conf.d/AuthUserFile.conf
DefaultRoot ~
AuthUserFile /etc/proftpd/ftpd.passwd
RequireValidShell off

$ id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ sudo ftpasswd --file /etc/proftpd/ftpd.passwd --passwd --name webadmin --home /usr/share/nginx/www --shell=/bin/false --uid 33

$ sudo chown -R www-data:www-data /usr/share/nginx/www

$ sudo service proftpd restart