nginx-https-CGI-post数据

nginx-https-CGI-post数据

一个C语言编写的CGI脚本测试demo。

环境搭建

中间件-nginx

nginx-download下载最新版本的nginx。安装openssl,也可以使用源代码进行安装,示例安装即为使用openssl源代码,–add-module添加其他模块,如–add-module=path/to/nginx_upload_module。

1
2
3
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-openssl=path/to/openssl #https配置
make
make install

访问本地80端口能看到nginx的欢迎界面。

本地https搭建

使用openssl生成共私钥,CA证书,客户端服务器证书。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 生成服务端私钥
openssl genrsa -out server.key 2048
# 生成服务端公钥
openssl rsa -in server.key -pubout -out server.pem
# 生成客户端私钥
openssl genrsa -out client.key 2048
# 生成客户端公钥
openssl rsa -in client.key -pubout -out client.pem
# 生成CA证书
openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
# 生成客户端服务端证书
# 服务端证书,向CA申请签名
openssl req -new -key server.key -out server.csr
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
# 客户端证书,向CA申请签名
openssl req -new -key client.key -out client.csr
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt

生成完毕,在nginx安装目录下新建一个ssl目录,用于存放服务器证书和密钥,配置nginx.conf。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# HTTPS server
#
server {
listen 443 ssl;
server_name localhost;

ssl_certificate ../ssl/server.crt;#服务器证书
ssl_certificate_key ../ssl/server.key;#服务器私钥

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;

ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
root html;
index index.html index.htm;
}
# CGI configure
location ~ \.cgi$ {
root /usr/local/nginx/cgi-bin;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

}

重启nginx,访问https//localhost:443/确定是否配置成功。

fcgiwrap运行CGI脚本

安装fcgiwrap用以启动C语言,php,bash等编写的应用。

1
2
3
sudo apt-get install libfcgi-dev
sudo apt-get install spawn-fcgi
sudo apt-get install fcgiwrap

服务会立即启动,查看服务状态。

1
2
systemctl status fcgiwrap.service
systemctl status fcgiwrap.socket

在nginx安装根目录下新建cgi-bin目录,编写一个测试demo,demo功能识别GET或POST方法,对POST方法的部分数据进行读,并写在本地服务器下,实现简单的数据上传。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcgi_stdio.h>
#include<unistd.h>
//#include<fcgi_config.h>
//#include<fcgiapp.h>

void sayHello(char *pQueryStr)
{
char *pName = NULL;
pName = strstr(pQueryStr,"name");
if(pName)
{
char *pTmp = pName + 5;
printf("Hello %s!\r\n",pTmp);
}
else
{
printf("No Name!\r\n");
}
return ;
}


void saveToFile(char *pContent,int contentLength)
{
FILE *fp = NULL;

fp = fopen("fateStealData","ab+");
if(fp)
{
printf("Preparing to write sth!\r\n");
fwrite(pContent,sizeof(char),contentLength,fp);
fclose(fp);
}
else
{
printf("Opening file error!\r\n");
}
return ;
}

int main()
{

while(FCGI_Accept() >= 0)
{
char *pMethod = NULL;
char *pQueryStr = NULL;
char *pContentType = NULL;
char *pPostContent = NULL;
//http header
printf("Content-Type: text/plain\r\n\r\n");

//content
pMethod = getenv("REQUEST_METHOD");
if(pMethod && !strcmp(pMethod,"GET"))
{
pQueryStr = getenv("QUERY_STRING");
if(pQueryStr)
{
sayHello(pQueryStr);
}
}
else if(pMethod && !strcmp(pMethod,"POST"))
{
pContentType = getenv("CONTENT_TYPE");
if(pContentType)
{
if(!strcmp(pContentType,"application/x-www-form-urlencoded"))
{
int contentLength = atoi(getenv("CONTENT_LENGTH"));
pPostContent = (char *)malloc(contentLength + 1);
if(pPostContent)
{
memset(pPostContent,0,contentLength + 1);
fread(pPostContent,sizeof(char),contentLength,stdin);
sayHello(pPostContent);
saveToFile(pPostContent,contentLength + 1);
free(pPostContent);
pPostContent = NULL;
}
}
else
{
printf("CONTENT_TYPE not supported now!\r\n");
}
}
}
printf("\r\n");
}

return 0;
}

​ 编译。

1
gcc mycgi.c -o mycgi.cgi -lfcgi

​ 放置在cgi-bin目录下。

demo测试

​ demo测试,post一段数据到服务器上,由于需要写文件,需要cgi-bin目录拥有写权限。

​ 配置nginx.conf,重启。

1
2
3
4
5
6
7
location ~ \.cgi$ {
root /usr/local/nginx/cgi-bin;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

​ 使用postman进行测试。post数据到https//ip/mycgi.cgi。

nginx1

​ 查看cgi-bin目录下是否生成了相应文件,测试完毕。

参考资料

Upload | NGINX
Nginx配置Web服务器详解
已安装nginx支持https配置
用Nginx搭建HTTPS服务器
FastCGI Developer’s Kit
Writing Hello World in FCGI with C++
How to execute CGI scripts using fcgiwrap
Spawns FastCGI Processes