PHP – OpenSSL 生成CA私钥&证书及签发带SAN的证书

生成CA私钥及证书:

参考Example #1 Creating a self-signed certificate

使用上面的方法可以生成CA证书并使用,但是如果使用上面的方法直接生成的自签名域名证书,即使你把(CA)证书加入到了受信任的根证书列表,也不会受浏览器信任:


NET::ERR_CERT_COMMON_NAME_INVALID

此服务器无法证实它就是 localhost – 它的安全证书没有指定主题备用名称。这可能是因为某项配置有误或某个攻击者拦截了您的连接。


你还需要把域名加入到SAN。

首先生成OpenSSL的配置文件:

通过上一步生成的配置文件生成CSR:

对CSR进行签名:

最后删除配置文件:

 

References:

https://secure.php.net/manual/en/function.openssl-csr-new.php

https://comm.support.ca.com/kb/adding-custom-x509-extensions-to-certificate-signing-requests/kb000042912

https://www.openssl.org/docs/manmaster/man5/x509v3_config.html#Basic-Constraints

https://github.com/openssl/openssl/blob/2cc7acd273bc39f1360aed52400d18bb65b88a95/apps/openssl.cnf#L36

https://bugs.php.net/bug.php?id=71050

https://stackoverflow.com/questions/30977264/subject-alternative-name-not-present-in-certificate

ERROR: failed to retrieve TCP_INFO for socket: Protocol not available (92)

 

PHP 7.2 compile on Debian Stretch

Libraries:

Configure:

Make

 

xmlrpc error 1:

Open Makefile, add

to the line(1933) where the error occured.

 

xmlrpc error 2:

 

find

in Makefile, add to the end of the line

 

readline error:

Open Makefile, searc

add “-lreadline”:

PHP线程安全与非线程安全版本的本质区别

php

在百度上搜“PHP 线程安全 非线程安全”,你肯定会找到这种话:

php-some

感觉这个没解释到点上。

 

线程和进程最大的根本区别就是内存数据的共享。

每个进程都独享一个虚拟内存[虚拟内存 = 物理内存 + SWAP/页面文件)]。

一个进程可以拥有多个线程,一般来说一个线程仅独享一个进程的虚拟内存中的一个函数栈帧。

 

程序储存数据有下面几种常用的方式:

自动变量: 自动变量是储存在栈中的,随着函数的调用而产生,结束而销毁。

静态(全局)变量: 静态分配的变量是随着程序的运行产生,程序的结束而销毁,这些变量储存在内存一个专门存放静态变量的区域。

堆: 即通过malloc()申请的内存,一旦申请后,直到调用free(),或程序结束后才释放。

 

其中造成“非线程安全”的主要是静态变量以及堆。

自动变量仅存在于函数自己的栈中,不管你如何修改其值,均不会影响其他函数(准确来说是线程)的数据。

静态变量独立储存于一个区域,这就意味着一个静态变量由整个进程的所有线程共享,一个线程修改了静态变量的值,将会改变其他线程读对该变量取得的结果,储存于堆的数据亦如此。

 

所谓“线程安全”,即采取了的措施,避免不同的线程同时对一个内存区域的数据进行修改。

例如某些函数的结果保存于静态分配的变量,或者是保存于堆中的一个区域,可以选择通过加锁,或互斥量来阻塞其他线程对这些函数的调用,但细心的话你也看到了“阻塞”二字,因此最佳的办法就是避免采用这些用到静态分配或堆的函数。

 

如果你用过PHP的Pthreads模块,并且理解了本文,那你应该明白为何Pthreads模块强制要求使用线程安全版本的PHP。

[PHP模块开发]获取单次请求所耗的CPU时间

数天前与一个学校中的朋友闲聊,对方提到了使用Hostker的经历,涉及到了一项“按CPU时间”计费的功能。

个人来说,是挺欣赏这一项收费策略的,毕竟有多少个使用虚拟主机的用户,就有多少种不同资源需求量,按照PHP对CPU资源的使用情况来计费,不仅实现公平收费,还能逼那些让资源占用多的用户占得谨慎点,比用CloudLinux的那些逼格高得多哈!

 

既然如此,就自己来动手实现一个。

计算CPU时间,并不难实现,Unix Like有提供这一个系统调用,所以嘛,根本不需要你自己计算……

我所知道相关的系统调用有两个,以下是他们的函数原型:

times()需要一个tms结构体的指针,tms结构体的格式如下:

tms_cutime和tms_cstime不太清楚是计算子线程还是子进程,毕竟目前我还没接触到多线程开发,不过一般情况下PHP还是使用单进程单线程模式的,只需要用到tms_utime和tms_stime。

tms结构体中的值的单位并非为秒,内核计时是有一个频率的,因此除以该计时频率的值,才能得到以秒为单位的值,使用sysconf(_SC_CLK_TCK)可以获取到该值。

times函数的返回值是一个过去的时间,我看了下,好像除以一百才是秒,所以两次调用的返回值之差除以一百可以得到自然流逝的时间。不过man page里面说The return value may overflow the possible range of type clock_t.,意思是返回值可能溢出。

 

clock()不需要任何参数,直接返回用户态和核心态使用的时间总和,同样,返回值的单位不是秒,需要除以一个常量: CLOCKS_PER_SEC。

 

我们来看看C计算从零到十亿需要多少CPU时间:

执行后返回以下结果:

times()函数获取到用户态耗时3.22秒,核心态耗时0.02秒,总CPU时间3.24秒,自然时间流逝3.21秒。

clock()函数取到3.25秒,和times()有点差距,毕竟调用times()也要耗时。

至于自然时间流逝比总CPU耗时短的问题,有两种情况。

第一种是我们获取开始时间并非真正在程序启动时就获取,而CPU时间的计算是内核在程序启动一刻开始计时的,程序启动到我们获取起始时间之间是有时间差的。

第二种是多线程,如果在自然时间一秒内同时使用满两个CPU核心,那么自然时间流逝是一秒,CPU时间就是两秒,不过这里是单线程编程,应该不涉及这种情况。

 

知道了如何调用这些API,接下来就是要弄成PHP模块了。

PHP的模块开发也不难,PHP已经为你准备好了一切,我来教你如何生成基本模块结构。

假设我们的模块名定为cputime。

下载PHP的源码,进入源码根目录下的ext目录,执行:

ext_skel会自动生成目录cputime及其需要的文件,进入cputime,编辑cputime.c。

我觉得我只需要告诉你,宏PHP_RINIT_FUNCTION(cputime)与PHP_RSHUTDOWN_FUNCTION(cputime)中的代码,分别在PHP开始解析前和PHP解析完毕后执行。

 

cputime.c修改完毕后,修改config.m4,找到类似的代码:

改成:

这样就能通过phpize生成模块了。

 

一切完毕后,按照正常使用PHP模块的方式编译,加载。

 

我们来看看PHP计算零到十亿需要多少时间:

一百零七秒多,人民群众喜闻乐见。

 

如果你想说你不会改cputime.c,这里还有一个成品: https://coding.net/u/yzs/p/PHP-CPUTIME-PRINT/git,可以把每次页面的时间记录追加到/tmp/uid_用户id_php_cputime中。不过你最好别指望能直接搬到生产环境上用,多个进程往同一个地址同时写,数据恐怕就出问题了呢。