# SA Homework4 Checklist ###### tags: `SA` ## Setup ### Installation ```shell sudo pkg install -y php73 php73-{extensions,zip,mbstring,GD,zlib,curl,openssl,pecl-imagick-im7,intl,fileinfo,pecl-APCu} nginx mysql80-server curl wget sudo pkg install -y php73-pdo_mysql ``` #### /etc/rc.conf ```shell php_fpm_enable="YES" nginx_enable="YES" mysql_enable="YES" firewall_enable="YES" firewall_type="open" ``` You may need to reboot. ### PHP config ```shell sudo cp /usr/local/etc/php.ini{-production,} ``` #### /usr/local/etc/php.ini ``` cgi.fix_pathinfo=0 expose_php=Off # hide php version ``` #### /usr/local/etc/php-fpm.d/www.conf ``` listen.owner = www listen.group = www listen.mode = 0660 ;listen = 127.0.0.1:9000 listen = /var/run/php-fpm.sock ``` ### Nginx config Edit `/usr/local/etc/nginx/nginx.conf`. ```nginx user www; worker_processes auto; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server_tokens off; server { listen 80; server_name hyperbola.nctu.me; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2 default_server; server_name hyperbola.nctu.me; root /usr/local/www/hyperbola.nctu.me; ssl_certificate /etc/ssl/hyperbola.nctu.me.pem; ssl_certificate_key /etc/ssl/hyperbola.nctu.me.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5; ssl_dhparam /etc/ssl/dhparam.pem; ssl_session_cache shared:SSL:40m; ssl_session_timeout 4h; ssl_session_tickets on; add_header Strict-Transport-Security "max-age=31536000" always; access_log /var/log/nginx/hyperbola.nctu.me.log; error_log /var/log/nginx/hyperbola.nctu.me.err.log; index index.html index.htm index.php; location / { try_files $uri $uri/ =404; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/local/www/nginx-dist; } # location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $request_filename; include fastcgi_params; } } } ``` ## Spec - [x] Setup name-based virtual host. - [x] Show different content when connecting using domain name/IP. ### Private page - [x] Place a webpage on `https://{your-intranet-IP}/private`. - [x] When accessing from intranet, it must show after passing. Basic Auth authentication with username `admin` and password `your-student-ID`. - [x] Access from public network should be denied (return 403) . ### Information hidden - [x] Hide NGINX/Apache version in header (5%). ```nginx server_tokens off; ``` ### HTTPS https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-in-ubuntu-16-04 - [x] Enable HTTPS (5%). Self-signed certificate is allowed. ```shell sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/hyperbola.nctu.me.key \ -out /etc/ssl/hyperbola.nctu.me.pem \ -subj '/CN=hyperbola.nctu.me' sudo openssl dhparam -out /etc/ssl/dhparam.pem 2048 ``` ```nginx ssl_certificate /etc/ssl/hyperbola.nctu.me.pem; ssl_certificate_key /etc/ssl/hyperbola.nctu.me.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5; ssl_dhparam /etc/ssl/dhparam.pem; ssl_session_cache shared:SSL:40m; ssl_session_timeout 4h; ssl_session_tickets on; ``` - [x] Supply `–k` option when testing with `curl`. - [x] Redirect to HTTPS automatically when attempting to connect to HTTP. ```nginx server { listen 80; server_name hyperbola.nctu.me; return 301 https://$server_name$request_uri; } ``` - [x] Enable HSTS. ```nginx add_header Strict-Transport-Security "max-age=31536000" always; ``` - [x] Enable HTTP2 on pages connected with HTTPS. Can be tested with `curl --http2`. Ensure that the server only provides ciphers not "blacklisted" by HTTP2. ```nginx listen 443 ssl http2; ``` ## PHP/PHP-FPM :::warning Use PHP7 or higher ::: - [x] Set up PHP such that access to `https://{yourdomain}/info-{your-student-ID}.php` gives response of `phpinfo()` (3%). - [x] Hide PHP version information in header (2%). ``` expose_php=Off # edit /usr/local/etc/php.ini ``` ## MySQL ### Setup ```shell sudo sysrc mysql_enable="YES" sudo service mysql-server start sudo mysql_secure_installation ``` ### Spec - [x] Set the transaction isolation levels to READ-COMMITTED (3%). Bonus: Explain why this and other isolation levels mean (+5%). ```sql SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT @@global.transaction_isolation; ``` [資料庫交易的 Isolation](https://medium.com/getamis/database-transaction-isolation-a1e448a7736e): * Read Uncommitted: 代表 transaction 可以讀到別的 transaction 尚未 commit 的資料,在這個等級中三個問題都沒有解決。 * Read Committed: 代表 transaction 只能讀到別的 transaction 已經 commit 的資料,沒有 commit 的話就不會讀到,在這個等級解決了 Dirty Read 的問題。 * Repeatable Read: 代表每次 transaction 要讀取特定欄位的資料時,只要 query 條件相同,讀取到的資料就會相同。在這個等級解決了 Non-repeatable reads 的問題。 * Serializable: 代表在多個 transaction 同時執行時,只要 transaction 的順序相同時,得到的結果一定相同。比如說 Transaction A 先執行了接下來再執行 Transaction B,在同樣的條件下,每次執行都會得到一樣的結果。在這個等級下連同 Phantom reads 也會一併被解決。 - [x] Create a MySQL user named `nc`. The password of the user is your student ID (3%). This user can only login from localhost (2%). ```sql CREATE USER 'nc'@'localhost' identified with mysql_native_password by '0716023'; FLUSH PRIVILEGES; SELECT host, user, authentication_string FROM mysql.user; ``` - [x] Create a database named `nextcloud`. ```sql CREATE DATABASE nextcloud; SHOW DATABASES; ``` - [x] User `nc` only have full privileges on database `nextcloud` (2%). ```sql GRANT ALL PRIVILEGES ON nextcloud.* TO 'nc'@'localhost'; FLUSH PRIVILEGES; SHOW GRANTS FOR 'nc'@'localhost'; ``` ## HTTP Applications You can have only one file index.php in the root at the path `https://{your-domain}/app`. - [x] `https://{your-domain}/app` displays `route: /`. - [x] `https://{your-domain}/app/{A}+{B}` displays `result: {A+B}`. - [x] `https://{your-domain}/app?name={string}` displays `Hello, {string}`. ```php $uri = substr($_SERVER['REQUEST_URI'], 4); // remove prefix /app if (isset($_GET['name'])) { echo "Hello, $_GET[name]"; } else if (preg_match('/^\\/[0-9]+\\+[0-9]+$/', $uri)) { $ploc = strpos($uri, "+"); $a = substr($uri, 1, $ploc-1); $b = substr($uri, $ploc + 1); $sum = $a + $b; echo "result: $sum"; } else { echo "route: $uri"; } ``` ## WebSocket * [Simple DEMO](https://medium.com/@cn007b/super-simple-php-websocket-example-ea2cd5893575) * This program crashes at client refresh, so just use it for test or demo. * You can use other WebSocket program you want. * You don’t need to support HTTP2 for WebSocket connection * You can use HTTP for this path if you cannot make it connected on port 443. ### Steps ```nginx http { upstream ws { server localhost:12345; } server { server_name hyperbola.nctu.me; # ...... location /wsdemo/ { proxy_pass http://ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } } ``` ### SPEC - [x] Connect WebSocket on port other than 80, 443 (ws://) (3%) - [x] Connect WebSocket on port 80 (ws://) (+3%) - [x] Connect WebSocket on port 443 (wss://) (+4%) ## Nextcloud * You can either install by pkg (v16) or download the latest version (v17). * Install on path `https://{your-domain}/nextcloud`. ### Insallation ```shell sudo pkg install -y php73-{zip,mbstring,GD,zlib,curl,openssl} cd /path/to/root/of/nextcloud sudo wget https://download.nextcloud.com/server/releases/nextcloud-17.0.2.zip sudo tar xf nextcloud-17.0.2.zip sudo chown -R www:www nextcloud sudo rm xf nextcloud-17.0.2.zip ``` #### Post-installation ```shell cd /path/to/root/of/nextcloud ## ensure that mysql-server is running sudo -u www ./occ -y db:convert-filecache-bigint ``` ### Nginx config Setup [nginx config](https://docs.nextcloud.com/server/15/admin_manual/installation/nginx.html). ```nginx user www; worker_processes auto; events { worker_connections 1024; } http { upstream php-handler { server unix:/var/run/php-fpm.sock; } include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server_tokens off; server { listen 80; server_name hyperbola.nctu.me; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2 default_server; server_name hyperbola.nctu.me; root /usr/local/www/hyperbola.nctu.me; ssl_certificate /etc/ssl/hyperbola.nctu.me.pem; ssl_certificate_key /etc/ssl/hyperbola.nctu.me.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5; ssl_dhparam /etc/ssl/dhparam.pem; ssl_session_cache shared:SSL:40m; ssl_session_timeout 4h; ssl_session_tickets on; access_log /var/log/nginx/hyperbola.nctu.me.log; error_log /var/log/nginx/hyperbola.nctu.me.err.log; index index.html index.htm index.php; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; add_header Referrer-Policy no-referrer; add_header X-Frame-Options "SAMEORIGIN"; add_header Strict-Transport-Security "max-age=31536000" always; fastcgi_hide_header X-Powered-By; location = /.well-known/carddav { return 301 $scheme://$host:$server_port/remote.php/dav; } location = /.well-known/caldav { return 301 $scheme://$host:$server_port/remote.php/dav; } client_max_body_size 512M; fastcgi_buffers 64 4K; gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; location / { rewrite ^ /index.php; } location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ { deny all; } location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) { deny all; } location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) { fastcgi_split_path_info ^(.+?\.php)(\/.*|)$; set $path_info $fastcgi_path_info; try_files $fastcgi_script_name =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $path_info; fastcgi_param HTTPS on; fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; fastcgi_pass php-handler; fastcgi_intercept_errors on; fastcgi_request_buffering off; } location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { try_files $uri/ =404; index index.php; } # Adding the cache control header for js, css and map files # Make sure it is BELOW the PHP block location ~ \.(?:css|js|woff2?|svg|gif|map)$ { try_files $uri /index.php$request_uri; add_header Cache-Control "public, max-age=15778463"; access_log off; } location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ { try_files $uri /index.php$request_uri; access_log off; } } } ``` ### Spec - [x] 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. - [x] When accessing `https://{your-domain}/sites/~{username}/` , it should show whatever {username} put in his `public_html`, with index index.html. #### Fix warnings - [x] Fix all the warnings in Settings/Overview page. * Edit `/usr/local/etc/php-fpm.d/www.conf` ``` env[PATH] = /usr/local/bin:/usr/bin:/bin ``` * Edit `/usr/local/etc/php.ini` ``` memory_limit = 1G ``` * Edit `/path/to/nexcloud/config/config.php` ``` 'memcache.local' => '\OC\Memcache\APCu' ```