文档章节

PHP7中用opcache.file_cache导出脚本opcode实现源代码保护

eechen
 eechen
发布于 2015/12/07 00:55
字数 920
阅读 8272
收藏 45

停止php-fpm(apache同理):
sudo /png/php/7.0.0/png_fpm stop

创建opcode缓存目录:
mkdir -m 777 /png/php/opcache_file_cache

在php.ini中配置:
zend_extension=/png/php/7.0.0/lib/php/extensions/no-debug-non-zts-20151012/opcache.so
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
;opcache不保存注释,减少opcode大小
opcache.save_comments=0
;关闭PHP文件时间戳验证
opcache.validate_timestamps=Off
;每60秒验证php文件时间戳是否更新
;opcache.revalidate_freq=60
opcache.fast_shutdown=1
;注意,PHP7下命令行执行的脚本也会被 opcache.file_cache 缓存.
opcache.enable_cli=1
;设置不缓存的黑名单
;opcache.blacklist_filename=/png/php/opcache_blacklist
opcache.file_cache=/png/php/opcache_file_cache
opcache.file_cache_only=0
opcache.enable=On

备份原来项目(以phpMyAdmin为例):
cp -R /png/www/example.com/public_html/app/pma /png/www/example.com/public_html/app/pma.bak

执行opcache_compile_file.php导出PHP脚本对应的opcode:
sudo /png/php/7.0.0/bin/php /png/www/example.com/public_html/app/opcache_compile_file.php
opcache_compile_file.php 内容如下:

<?php
function getfiles( $path , &$files = array() ) {
	if ( !is_dir( $path ) ) return null;
	$handle = opendir( $path );
	while ( false !== ( $file = readdir( $handle ) ) ) {
		if ( $file != '.' && $file != '..' ) {
			$path2 = $path . '/' . $file;
			if ( is_dir( $path2 ) ) {
				getfiles( $path2 , $files );
			} else {
				if ( preg_match( '%\.php$%' , $file ) ) {
					$files[] = $path2;
				}
			}
		}
	}
	return $files;
}
// 获取指定目录及其子目录下的所有PHP文件
$files = getfiles('/png/www/example.com/public_html/app/pma');
foreach($files as $file){
	opcache_compile_file($file); //编译PHP文件生成opcode
	file_put_contents($file, ''); //清空原来的PHP脚本
	echo $file."\n";
}
echo 'Total PHP Files: '.count($files)."\n";

或者使用PHP的SPL库里提供的递归目录迭代器RecursiveDirectoryIterator实现递归编译PHP:

<?php
opcache_compile_files('/png/www/example.com/public_html/app/pma');
function opcache_compile_files($dir) {
	foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $v) {
		if(!$v->isDir() && preg_match('%\.php$%', $v->getRealPath())) {
			opcache_compile_file($v->getRealPath());
			echo $v->getRealPath()."\n";
		}
	}
}

把缓存目录所有者设为php-fpm运行用户,我这里是png:
sudo chown -R png:png /png/php/opcache_file_cache/

启动php-fpm:
sudo /png/php/7.0.0/png_fpm start
访问phpMyAdmin:
http://www.example.com/app/pma/

phpMyAdmin的PHP文件一一对应的opcode(后缀为.php.bin)生成在:
/png/php/opcache_file_cache/xxx/png/www/example.com/public_html/app/pma
其中xxx是一个32位的md5编码的字符串.
部署到目标服务器的时候,需要保留项目中内容被清空的PHP脚本.
而且路径一定要对应导出opcode时的路径,文中的就是:
/png/www/example.com/public_html/app/pma

另外,PHP还可以使用函数php_strip_whitespace()删除PHP源码中的注释和空格.

后话:
opcache.file_cache是PHP7对hhvm.repo.central.path的反击,鸟哥威武!
opcache.file_cache对比PHP5时代APC的apc_bin_dumpfile和apc_bin_loadfile来说,
导出和导入操作都由opcache完成,显然ZendOpcache比APC更加自动化.
那个md5串由 PHP_VERSION / ZEND_EXTENSION_BUILD_ID / ZEND_BIN_ID 确定:

php-src/ext/opcache/zend_file_cache.c: zend_file_cache_get_bin_file_path ZCG(system_id)
php-src/ext/opcache/ZendAccelerator.c: accel_gen_system_id ZCG(system_id) 
#define ZEND_EXTENSION_BUILD_ID "API" ZEND_TOSTR(ZEND_EXTENSION_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA
#define ZEND_BIN_ID "BIN_" ZEND_TOSTR(SIZEOF_CHAR) ZEND_TOSTR(SIZEOF_INT) ZEND_TOSTR(SIZEOF_LONG) ZEND_TOSTR(SIZEOF_SIZE_T) ZEND_TOSTR(SIZEOF_ZEND_LONG) ZEND_TOSTR(ZEND_MM_ALIGNMENT)

因为Ubuntu上编译的PHP7,打包依赖库后放到CentOS上运行,这个md5串是相同的.
可以肯定的是,Linux上导出的opcode不能放到Windows上运行,反之也是如此.

Beast加密过的PHP文件,也一样能看到PHP文件对应的opcode,
因为Beast解密后,还是一样需要调用zend_compile_file生成页面的opcode,
而opcode是可以用VLD(Vulcan Logic Disassembler)这类PECL扩展查看的.
php -dvld.active=1 -S 127.0.0.1:8080
curl http://127.0.0.1:8080/
也就是说,PHP脚本加密能够避免脚本被恶意篡改,但脚本里的数据仍然是可见的.
所以,文中的opcache.file_cache用来保护代码逻辑应该还是可以的,
但不能确保里面定义的量的安全,比如加密密钥.存也可以,但防君子不防小人,门槛高点而已.

Zend Guard和ionCube加密的PHP脚本可以用DeZender/De-ionCube解密:
http://dezender.net/
Java字节码和Android APK可以用Java Decompiler反编译:
http://jd.benow.ca/
Python脚本可以编译成pyc文件,不过pyc文件也很容易被反编译.
所以包括opcache.file_cache这样的代码保护,也只能防君子不防小人.

 

© 著作权归作者所有

共有 人打赏支持
eechen

eechen

粉丝 980
博文 107
码字总数 55962
作品 1
深圳
加载中

评论(27)

eechen
eechen

引用来自“Tai7sy”的评论

一处错误:
必须设置 file_only=0(关闭), 否则 opcache_compile_file 无法调用
php --ri 'Zend OPcache' 并没有你说的 file_only 配置项.
你说的应该是 opcache.file_cache_only.
刚才测试了PHP 7.1,确实需要配置:
opcache.file_cache_only=0
否则会提示:
Notice: Zend OPcache seems to be disabled, can't compile file
T
Tai7sy
一处错误:
必须设置 file_only=0(关闭), 否则 opcache_compile_file 无法调用
天睿云计算
天睿云计算

引用来自“eechen”的评论

引用来自“天睿云计算”的评论

zend 加密软件 不再支持php7了
ioncube提供的PHP脚本加密服务还是支持PHP7的,甚至支持ARM架构的Linux,比如树莓派的Raspbian(基于Debian ARM).

@eechen 嗯,ioncube10还在开发中
eechen
eechen

引用来自“天睿云计算”的评论

zend 加密软件 不再支持php7了
ioncube提供的PHP脚本加密服务还是支持PHP7的,甚至支持ARM架构的Linux,比如树莓派的Raspbian(基于Debian ARM).
天睿云计算
天睿云计算
zend 加密软件 不再支持php7了
SaFlyORG
SaFlyORG
我现在用的apache + mod_php,请问是不是要换成 apache + php-fpm
SaFlyORG
SaFlyORG
已经chown -R apache:apache 目标目录
SaFlyORG
SaFlyORG
@eechen bin生成成功了,并且php -f 某个php文件可以正常执行。但通过http方式访问就是空白页。请问是apache的原因么?
SaFlyORG
SaFlyORG

引用来自“eechen”的评论

@AbyssConG 你需要确保你的程序(httpd)对opcache.file_cache目录有写权限.
把opcache.file_cache目录的所有者设为httpd的运行用户.
已经成功了,十分感谢大神89
SaFlyORG
SaFlyORG

引用来自“eechen”的评论

@AbyssConG 你需要确保你的程序(httpd)对opcache.file_cache目录有写权限.
把opcache.file_cache目录的所有者设为httpd的运行用户.
感谢回复:) 我把目录权限设为777,可还是不能成功。。。是不是要在apache关闭的情况下,php -f opcache_compile_file.php 才能成功?
PHP开发Linux桌面应用和Android应用思路

PHP7中用opcache.file_cache导出脚本opcode实现源代码保护 http://my.oschina.net/eechen/blog/539995 下载PHPDroid: 基于WebView和PHP内置HTTP服务器开发Android应用 http://my.oschina.ne......

eechen
2015/09/05
0
14
php7性能优化

之前一直使用的PHP版本都是6.5/6.6的,这次的项目开发要求使用PHP7,在网上大概看了下,发现PHP7的性能较之前相比提升了很多,所以使用PHP7我也没啥意见,欣然接受。 今天温州一家客户做活动...

西红柿炒肉
2017/11/09
0
0
PHP历史之3:秣兵历马的PHP7-王者归来

提起PHP7,就不得不提到源自FB的HHVM,据说安装了这种优化器,可以高效的PHP运行环境提升PHP性能9倍以上 当然PHP7已经超过了这种性能。 伴随着PHP 7的发布,这几天关于PHP 7性能和兼容性成了大...

ccpit2b2c
06/26
0
0
PHP7优化提高性能的几个Tips

PHP7已经发布了, 作为PHP10年来最大的版本升级, 最大的性能升级, PHP7在多放的测试中都表现出很明显的性能提升, 然而, 为了让它能发挥出最大的性能, 我还是有几件事想提醒下. 1. Opcache 记得...

English0523
2015/12/29
0
0
追踪 PHP7 运行的 Nginx 模块--ngx_php7_tracker

ngxphp7tracker ngx_php7 的分支,追踪php7脚本运行的opcode、函数栈调用的nginx模块。 环境 PHP 7.0.* - nginx-1.6.3 安装 $ wget http://php.net/distributions/php-7.0.14.tar.gz$ tar x......

rryqszq
2016/12/16
486
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Zookeeper总结

Zookeeper的部分概念 什么是zookeeeper? Zookeeper是一个分布式服务的协调中心 zookeeper节点的角色类型? Leader(领导者)、Follower(跟随者)、Observer(观察者) Leader 负责更新系统...

DemonsI
8分钟前
0
0
Redis学习笔记

常用命令 从Docker进入Redis的命令 sudo docker exec -it redis /bin/bash

OSC_fly
9分钟前
0
0
SqlServer查询某个日期的数据

select * from View_ZJMONITORINGCORROSION where ENTERDATE > CONVERT(datetime,DATEADD(day,1,'2017/12/28 14:53:07'))...

笑丶笑
10分钟前
0
0
常用编码规范

Standard characters https://ascii.cl/

yeahlife
12分钟前
0
0
flannel实战

docker swarm mode的出现是个里程碑,官方原生的编排调度看起来都成雏形了,但是swarm mode和容器外部系统的对接、网络性能始终不尽人意,swarm mode下各种开源周边不能使用,感觉swarm mod...

China_OS
13分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部