Web Server
Network
-
Intranet
A VM with a host-only adapter connecting to the same network of the original machine-
創立Host網卡
Create > enable DHCP server
-
將網卡加到VM
VM Settings > Network
Adapter 2 選Host-only Adapter
-
FreeBSD
/etc/rc.conf
新增網卡ifconfig_em1="DHCP"
reboot -n //重開機 ifconfig //查看網路設定
會看到新的網卡
em1 192.168.56.101
-
-
Public
The Wireguard VPN (10.113.0.0/16)
HTTP Server
Nginx
Install Nginx
pkg install nginx
Enable Nginx when reboot
sudo sysrc nginx_enable=yes
啟動nginx
service nginx start
在本機browser輸入ip後會看到這個頁面
(如果要用外網ip 本機要記得先連上VPN)
Configures
Virtual Host
❑ Setup a name-based virtual host
❑ Show different content when connecting using domain
name/IP
- Get a domain name
- 自簽SSL
mkdir /usr/local/etc/nginx/ssl
sudo openssl req -x509 -nodes -day 365 \
-newkey rsa:2048 -key out /usr/local/etc/nginx \
/ssl/nginx.key -out /usr/local/etc/nginx/ssl/nginx.crt
-
Configuration
/usr/local/etc/nginx/nginx.conf
(
location /
是ip會看到的頁面)http { ................................... ................................... ................................... # Hide the server version in header server_tokens off; # SSL認證 ssl_certificate /usr/local/etc/nginx/ssl/nginx.crt; ssl_certificate_key /usr/local/etc/nginx/ssl/nginx.key; # Using IP server { # web聽port 80 listen 80; # https聽port 443、enable SSL & HTTP2 listen 443 ssl http2; # public vpn ip server_name 10.113.0.98; location / { # Base on nakedhtml這個資料夾 root /usr/local/www/nginx/nakedhtml; # 首頁是資料夾nakedhtml中的index.html index index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/local/www/nginx-dist; } } # Using domain name server { listen 443 ssl http2; #server_name localhost; # Domain name as name-based virtual host server_name weelian.nctu.me; # SSL認證 ssl_certificate /usr/local/etc/nginx/ssl/nginx.crt; ssl_certificate_key /usr/local/etc/nginx/ssl/nginx.key; #charset koi8-r; #access_log logs/host.access.log main; add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "none" always; add_header X-XSS-Protection "1; mode=block" always; # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; index index.html index.php; root /usr/local/www/nginx; # domain name root index location / { index index.html index.htm; } ................................... ................................... ................................... } ................................... ................................... ................................... }
啟用HTTPS
Enable HSTS(HTTP Strict Transport Security): 放在domain name server
Redirect HTTP to HTTPS: 加在http{}裡的最後面
http {
...................................
...................................
...................................
# Using domain name
server {
listen 443 ssl http2;
# Enable HSTS
add_header Strict-Transport-Security "max-age=31536000;
includeSubDomains" always;
...................................
...................................
}
...................................
...................................
...................................
server {
listen 80;
server_name weelian.nctu.me;
return 301 https://weelian.nctu.me$request_uri;
}
}
Webpage /private
- When accessing from intranet, it must show after passing Basic Auth authentication with username admin and password {your-student-ID}
- Access from public network should be denied (return 403)
-
Auth Basic
設定帳號密碼sudo sh -c "echo -n 'admin:' >> /usr/local/www/nginx/.htpasswd" sudo sh -c "openssl passwd -apr1 >> /usr/local/www/nginx/.htpasswd"
-
設定
/usr/local/www/nginx/.htpasswd
權限
!正確!-rw-r----- www www .htpasswd
如果是原本的
-rw-r----- root wheel .htpasswd
外網 -> 403 Forbidden
內網輸入帳密後 -> An error occured -
nginx.conf
................................... ................................... ................................... # Using domain name server { ................................... ................................... # domain name root index location / { index index.html index.htm; } location /private { # allow Intranet allow 10.113.0.98; allow 192.168.56.101; # deny Internet deny all; auth_basic "Authorization Required"; auth_basic_user_file /usr/local/www/nginx/.htpasswd; alias /usr/local/www/nginx/secret; index index.html index.htm; } ................................... ................................... ...................................
PHP/PHP-FPM
Set up PHP such that access to https://{your- domain}/info-{your-student-ID}.php gives response of phpinfo()
-
Install php ver 7.3.0
pkg install php73 php73-mysqli
-
建立 php.ini
建立php.ini-production 的 soft-link 給 php.inicd /usr/local/etc sudo cp php.ini-production php.ini
-
Enable PHP
sudo sysrc php_fpm_enable=yes sudo service php-fpm start
-
Configure
nginx.conf
upstream php-handler { server 127.0.0.1:9000; #server unix:/var/run/php/php7.2-fpm.sock; } ................................... ................................... ................................... # Using domain name server { location ~ \.php$ { root /usr/local/www/nginx; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
-
定義SCRIPT_FILENAME
預設安裝的 Nginx FastCGI 參數檔裡面沒有定義 SCRIPT_FILENAME 這個變數
因此我們要把他加進去sudo vim /usr/local/etc/nginx/fastcgi_params
找到SCRIPT_FILENAME
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
-
info.php
<?php phpinfo(); ?>
-
改檔名
cd /usr/local/www/nginx-dist sudo mv info.php info-W081001.php
這樣去 https://weelian.nctu.me/info-W081001.php
就會看到phpinfo()
-
Hide PHP version in response header
/usr/local/etc/php.ini
expose.php=off
MySQL
Prepare for NextCloud
Install MySQL
portsnap fetch update
cd /usr/ports/databases/mysql57-server
sudo make WITH_CHARSET=utf8 install clean
Configuration
/usr/local/etc/my.conf
Start MySQL daemon
sudo /usr/local/etc/rc.d/mysql-server start
Login
login mysql as root with passwd
mysql -u root mysql -p
Create Database, User
Create a MySQL user named ‘nc’ and a database named ‘nextcloud’, which satisfies:
• The password of the user is your student ID
• This user can only login from localhost
• This user only have full privileges on database ‘nextcloud’
> create DATABASE nextcloud;
> show database;
> GRANT ALL ON nextcloud.* TO nc@localhost IDENTIFIED BY 'W081001';
> quit
Login as nc
mysql -u nc nextcloud -p
Set the transaction isolation levels to READ-COMMITED
> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITED;
> SELECT @@TX_ISOLATION;
HTTP Applications
Basic App Router
There are three path displaying different contents:
- https://{your-domain}/app
Display route: / - https://{your-domain}/app/{A}+{B} (A, B are integers)
Display result: {value of A+B} - https://{your-domain}/app?name={string}
Display Hello, {string}
app/index.php
<?php $input = $_SERVER["QUERY_STRING"]; if(strlen($input)>0){ $ars = explode("=",$input); if(strlen($ars[1])>0){ echo "Hello, $ars[1]"; } else{ $arr = explode("+",$input); $sum = (int)$arr[0]+(int)$arr[1]; echo "result: $sum"; } } else{ echo 'route: /'; } ?>
nginx.conf
location /app { alias /usr/local/www/nginx/app; index index.php; try_files $uri $uri/ @test; } location @test { rewrite ^/app/(.*)\+(\w+)\.?.*$ /app?$1+$2; }
WebSocket
- This program crashes at client refresh, so just use it for test or demo
- You don’t need to support HTTP2 for WebSocket connection
- Configure your HTTP server such the program run appropriately that when accessing http(s)://{your- domain}/wsdemo
- Let it be connected on port 443(wss://)
Original: WebSocket is on port 12345
Goal: connect websocket on port 443
In nginx.conf
...................................
...................................
...................................
upstream websocket {
server 0.0.0.0:12345;
}
# Using domain name
server {
location /wsdemo {
alias /usr/local/www/nginx/wsdemo;
index websockets.html;
# proxy_pass http://websocket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /public {
proxy_pass http://websocket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
In wsdemo/websockets.html
<html>
<body>
<div id="root"></div>
<script>
# var host = 'ws://0.0.0.0:12345/websockets.php';
var host = 'wss://weelian.nctu.me/public';
var socket = new WebSocket(host);
socket.onmessage = function(e) {
document.getElementById('root').innerHTML = e.data;
};
</script>
</body>
</html>
In wsdemo/websockets.php
<?php
$address = '0.0.0.0';
$port = 12345;
// Create WebSocket.
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, $address, $port);
socket_listen($server);
$client = socket_accept($server);
// Send WebSocket handshake headers.
$request = socket_read($client, 5000);
preg_match('#Sec-WebSocket-Key: (.*)\r\n#', $request, $matches);
$key = base64_encode(pack(
'H*',
sha1($matches[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
));
$headers = "HTTP/1.1 101 Switching Protocols\r\n";
$headers .= "Upgrade: websocket\r\n";
$headers .= "Connection: Upgrade\r\n";
$headers .= "Sec-WebSocket-Version: 13\r\n";
$headers .= "Sec-WebSocket-Accept: $key\r\n\r\n";
socket_write($client, $headers, strlen($headers));
// Send messages into WebSocket in a loop.
while (true) {
sleep(1);
$content = 'Now: ' . time();
$response = chr(129) . chr(strlen($content)) . $content;
socket_write($client, $response);
}
我一開始在執行socket的時候 出現Error
PHP Fatal Error: Uncaught Error: Call to undefined function socket_create() in....
後來發現是因為沒裝Socket Extension
cd /usr/ports/lang/php73-extensions
make config install clean
[x]socket
Nextcloud
要在{domain}/nextcloud
-
Install
要先用pkg install 才會有完整的php-fmppkg search nextcloud pkg install nextcloud-php-73
pkg裝好的nextcloud 會在
/usr/local/www
再把它刪掉 用本來的zip替換
改權限sudo chown -R www:www nextcloud
-
Configuration in
nginx.conf
Google: Nextcloud in a subdir of nginx
copy & paste innginx.conf
如果開{domain}/nextcloud 出現An error occured
-> 重開php-fpmsudo service php-fpm restart
or
-> kill PIDps aux | grep php sudo kill {php pid} sudo service php-fpm start
在一開始 Create user時 記得要選MySQL DB
-
Personal Webpage
- Each user in Nextcloud can put static(PHP is not needed) contents(img, html, css, js, etc.) in the public_html directory under their home
- When accessing https://{your-domain}/sites/~{username}/ , it should show whatever {username} put in his public_html, with index index.html
location /sites { try_files $uri $uri/ @ncsites; } location @ncsites { rewrite ^/sites/\~(.*) /nextcloud/data/$1/files/public_html/index.html; }