海运的博客

nginx配置webdav及使用curl测试

发布时间:February 2, 2021 // 分类:Nginx // No Comments

需安装http-dav-ext扩展,有时使用非标准webdav客户端删除目录时最后不带/,nginx删除目录失败返回409,alias不支持rewrite使用root。

  location /webdav/ {
    satisfy any;
    allow 127.0.0.1;
    deny all;
    #root /;
    #if (-d $request_filename) { rewrite ^(.*[^/])$ $1/ break; }
    alias /webdav/;
    dav_methods PUT DELETE MKCOL COPY MOVE;
    dav_ext_methods PROPFIND OPTIONS;
    dav_access user:rw group:r all:r;
    create_full_put_path  on;
    port_in_redirect off;
    autoindex on;
    autoindex_localtime on;
    charset utf-8;
    auth_basic "Login";
    auth_basic_user_file htpasswd;
  }

配置nginx webdav不同用户使用不同的家目录:

map $remote_user $home {
  default      $remote_user;
  ''           guest;
}
server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name _;

  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;

  try_files $uri /;

  location / {
    #if (-d $request_filename) { rewrite ^(.*[^/])$ $1/ break; }
    alias /data/webdav/$home/;
    #dav_methods PUT DELETE MKCOL COPY MOVE;
    dav_ext_methods PROPFIND OPTIONS;
    dav_access user:r group:r all:r;
    create_full_put_path on;
    port_in_redirect off;
    autoindex on;
    autoindex_localtime on;
    charset utf-8;
    auth_basic "Login";
    auth_basic_user_file htpasswd;
  }

  #access_log off;
  access_log /var/log/nginx/webdav.log;
  error_log  /var/log/nginx/webdav_error.log;
}

使用curl测试webdav:
新建目录,注意最后一定要带/,不然返回409,MKCOL can create a collection only

curl -X MKCOL https://www.haiyun.me/webdav/test/

上传文件:

curl -T filename https://www.haiyun.me/webdav/

重命名文件:

curl -X MOVE --header 'Destination:https://www.haiyun.me/webdav/newname' https://www.haiyun.me/webdav/filename

删除文件:

curl -X DELETE https://www.haiyun.me/webdav/filename

php协程异步扩展swoole使用

发布时间:January 17, 2021 // 分类:PHP // No Comments

ubuntu 20.04 php7.4编译安装swoole:

apt install php-cli php-dev libcurl4-openssl-dev php-curl libc-ares-dev
wget https://github.com/swoole/swoole-src/archive/v4.8.13.tar.gz
tar zxf v4.8.13.tar.gz
cd swoole-src-4.8.13
phpize
./configure --enable-openssl --enable-http2 --enable-swoole-curl --enable-cares
make && make install
echo 'extension=swoole.so' > /etc/php/7.4/cli/conf.d/20-swoole.ini
php --ri swoole
#减小swoole.so文件的大小
strip -s /usr/lib/php/20190902/swoole.so

debian12安装swoole5:

apt install php-cli php-dev libcurl4-openssl-dev php-curl libc-ares-dev libbrotli-dev
wget https://github.com/swoole/swoole-src/archive/refs/tags/v5.1.4.tar.gz
./configure --enable-openssl --enable-swoole-curl --enable-cares

swoole原生协程http客户端:

<?php
//Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);
$count = 10;
Co\run(function () use (&$result, $count) {
  $wg = new \Swoole\Coroutine\WaitGroup();
  $result = [];
  for ($i = 1; $i <= $count; $i++) {
    $wg->add();
    go(function () use ($i, $wg, &$result) {
      $cli = new Swoole\Coroutine\Http\Client('www.baidu.com', 80);
      $cli->set(['timeout' => 10]);
      $cli->setHeaders([
        'Host' => 'www.baidu.com',
        'User-Agent' => 'Mozilla/5.0 Firefox/78.0',
      ]);
      $cli->get('/');
      $result[$i] = $cli->getStatusCode();
      $cli->close();
      $wg->done();
    });
  }
  $wg->wait();
});
var_dump($result);

以hook方式协程运行php curl:

<?php
//Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);
Co\run(function () {
  $chan = new Swoole\Coroutine\Channel(10);
  for ($i = 1; $i <= 10; $i++) {
    go(function () use ($i, $chan) {
      $header = array(
        'User-Agent: Mozilla/5.0 Firefox/78.0'
      );
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, "http://www.baidu.com");
      curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_exec($ch);
      $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);
      $chan->push(['index' => $i, 'code' => $code]);
    });
  }
  for ($i = 1; $i <= 10; $i++) {
    $res = $chan->pop();
    var_dump($res);
  }
});

ubuntu通过dropbear ssh远程解锁luks rootfs全盘加密

发布时间:January 1, 2021 // 分类: LUKS // No Comments

之前使用preseed安装ubuntu luks全盘加密,这样每次重启系统都要通过vnc输入密码,可以将dropbear添加到initramfs,通过ssh解锁要方便很多。
安装dropbear-initramfs:

apt install dropbear-initramfs

安装时会提示:

dropbear: WARNING: Invalid authorized_keys file, remote unlocking of cryptroot via SSH won't work!

因为生成initramfs时要包含/etc/dropbear-initramfs/authorized_keys,复制ssh验证密钥:

#本地执行
ssh-copy-id  root@www.haiyun.me
#远程执行
cp -p ~/.ssh/authorized_keys /etc/dropbear-initramfs/

修改dropbear ssh端口:

echo 'DROPBEAR_OPTIONS="-p 2222"' >> /etc/dropbear-initramfs/config

配置initramfs ip:

#IP="${ip_address}::${gateway_ip}:${netmask}:${optional_fqdn}:${interface_name}:${auto_config}:${name_server}
echo 'IP=192.168.1.2::192.168.1.1:255.255.255.0::eth0:none:1.1.1.1' >> /etc/initramfs-tools/initramfs.conf

ip配置也可添加到grub启动参数:

GRUB_CMDLINE_LINUX="ip=192.168.1.2::192.168.1.1:255.255.255.0::eth0:none:1.1.1.1"

可选修改cryptroot-unlock解锁程序通过参数输入加密密码:

sed -i  '/^set/i if [ ! -n "\$1" ] ; then echo "use cryptroot-unlock password";exit;fi' /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock
sed -i 's/read -rs/#read -rs/' /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock
sed -i 's/\$REPLY/\$1/' /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock

重新生成initramfs:

update-initramfs -u -k all

重启后通过ssh连接执行解锁luks:

cryptroot-unlock password

虽然/usr/share/initramfs-tools/scripts/init-bottom/dropbear有包含解锁luks后删除ip信息,但是启动后还是包含在initramfs内配置的ip信息,使用ubuntu在配置网络前清除ip信息:

sed -i '/iface eth0/a pre-up ip addr flush dev eth0' /etc/network/interfaces

20240325更新,debian12新版本ssh不能登录,提示:

debug1: Offering public key: /dev/shm/id_rsa RSA SHA256:xxxxx explicit                    
debug1: send_pubkey_test: no mutual signature algorithm                                                                         
debug1: No more authentication methods to try.  
root@www.haiyun.me: Permission denied (publickey).  

添加ssh配置:

cat .ssh/config 
Host *
    PubkeyAcceptedKeyTypes=+ssh-rsa
    HostKeyAlgorithms=+ssh-rsa

使用php调用expect ssh远程自动解锁luks:

<?php
ini_set("expect.timeout", 5);
ini_set("expect.loguser", "off");
$host = "www.haiyun.me";
$port = 22;
$pass = "xxxxxx";
$stream = expect_popen("ssh -o StrictHostKeyChecking=no -p {$port} root@{$host}");
$cases = array(
  array("password:", "pass"),
  array("Enter 'help'", "shell"),
  array("Please unlock disk", "unlock"),
  array("set up successfully", "sus"),
  array("Permission denied", "den"),
  array("cryptsetup failed", "fai")
);

while (true) {
  switch (expect_expectl($stream, $cases)) {
  case "den":
    echo 'Permission denied'.PHP_EOL;
    break 2;
  case "pass":
    fwrite($stream, "password\n");
    break;
  case "shell":
    fwrite($stream, "/usr/bin/cryptroot-unlock\n");
    //fwrite($stream, "/usr/bin/cryptroot-unlock {$pass}\n");
    break;
  case "unlock":
    fwrite($stream, "{$pass}\n");
    break;
  case "fai":
    echo 'unlock failed, bad password or options?'.PHP_EOL;
    break 2;
  case "sus":
    echo 'unlock sus'.PHP_EOL;
    break 2;
  case EXP_TIMEOUT:
    echo 'timeout'.PHP_EOL;
    break 2;
  case EXP_EOF:
    echo 'eof'.PHP_EOL;
    break 2; 
  default:
    die("Error has occurred!");
  }
}
fclose ($stream);

php调用ssh2扩展远程解锁luks加密:

<?php
$host = 'www.haiyun.me';
$port = 2222;
$pass = 'xxxx';
if (!($conn = ssh2_connect($host, $port, array('hostkey'=>'ssh-rsa')))) {
  die("conn fail\n");
}
//注意路径不要使用~/.ssh/id_rsa.pub,会遇到段错误和其它莫名其妙的问题
if (ssh2_auth_pubkey_file($conn, 'root', '/root/.ssh/id_rsa.pub', '/root/.ssh/id_rsa')) {
  echo "auth sus\n";
} else {
  die("auth fail\n");
}
function expect($stream, $match) {
  $time = time();
  $res = '';
  while(!feof($stream)){
    //if (($buffer = fgets($stream, 4096)) !== false) {
    if (($buffer = fread($stream, 4096)) !== false) {
      $res .= $buffer;
    }
    if (stristr($res, $match)) {
      return 'sus';
    }
    $now = time();
    if (($now - $time) >= 10) {
      return 'timeout';
    }
    usleep(100);
  }
  return 'disconnect';
}
 
$shell=ssh2_shell($conn, 'xterm');
fwrite($shell, "/usr/bin/cryptroot-unlock\n");
$res = expect($shell, 'Please unlock disk');
if ($res == 'sus') {
  fwrite($shell, "{$pass}\n");
  $res = expect($shell, 'set up successfully');
  if ($res == 'sus') {
  }
  var_dump($res);
}

发现的问题:此方法在ubuntu20.04使用编译的4.14内核bbrplus下导致系统启动很慢,5.4及5.10内核测试正常。
另外一种通过dracut生成initramfs调用openssh解锁luks的方法:
https://github.com/gsauthof/dracut-sshd
参考:
https://hamy.io/post/0009/how-to-install-luks-encrypted-ubuntu-18.04.x-server-and-enable-remote-unlocking/

linux下修复硬盘扇区错误及扫描坏道并修复

发布时间:December 30, 2020 // 分类: // No Comments

查看syslog日志发现有硬盘提示扇区错误:

Dec 30 07:08:27 ubuntu-20 kernel: [34767.158065] blk_update_request: critical medium error, 
dev sda, sector 1729898440 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0

badblocks查看出错的扇区数量,-b指定每次扫描的区块大小,设置为和扇区大小一致,1729898440为日志提示出错的扇区位置,1729898499指定扫描扇区的终止位置,扫描后可以看到共有8个扇区出错。

badblocks -b 512 /dev/sda 1729898499 1729898440
1729898440
1729898441
1729898442
1729898443
1729898444
1729898445
1729898446
1729898447

写入修复坏掉的扇区,注意会丢失之前的数据,如果有坏道硬盘会自动重映射坏掉的扇区。

badblocks -b 512 -w /dev/sda 1729898447 1729898440

扫描整盘,-b指定每次扫描的块大小,如果用于扇区写入为512,文件系统隔离为4096,-s显示进度,-v详细输出。

badblocks -b 512 -s -v -o badblocks.log /dev/sdf

读取生成的坏块列表使用badblocks写测试能否修复或重映射扇区。

<?php
$list = file('badblocks.log');
$arr = array();
$i = 0;
$last = 0;
foreach ($list as $v) {
  $v = trim($v);
  if (!$v) {
    continue;
  }
  if (!$last) {
    $arr[$i][] = $v;
    $last = $v;
    continue;
  }
  if (($v - $last) == 1) {
    $arr[$i][] = $v;
  } else {
    $i++;
    $arr[$i][] = $v;
  }
  $last = $v;
}
foreach ($arr as $vv) {
  if (count($vv) > 1) {
    $start = reset($vv);
    $end = end($vv);
  } else {
    $start = reset($vv);
    $end = reset($vv);
  }
  echo '/usr/sbin/badblocks -w -s -v /dev/sdf '."$end $start".PHP_EOL;
  shell_exec('/usr/sbin/badblocks -w -s -v /dev/sdf '."$end $start");
}

也可使用hdparm和dd写扇区:

hdparm --write-sector 77610960 --yes-i-know-what-i-am-doing /dev/sdf
dd if=/dev/zero of=/dev/sdf bs=512 seek=77610960 count=1

或重写整个硬盘:

dd iflag=fullblock oflag=direct conv=noerror,notrunc if=/dev/zero of=/dev/sdf bs=1M

对于不能修复的坏块让文件系统隔离,未经验证。

e2fsck -l badblocks.log /dev/sdf
mkfs -l badblocks.log /dev/sdf

参考:
https://zhuanlan.zhihu.com/p/31899347
https://www.linuxcool.com/badblocks
https://lug.ustc.edu.cn/wiki/linux_digest/badblocks/
https://tomjamescn.github.io/post/2019-06-16-repair-hard-disk-with-bad-sectors/
https://unix.stackexchange.com/questions/229354/how-to-ignore-write-errors-while-zeroing-a-disk/229362
https://superuser.com/questions/1322780/fix-or-reallocate-a-bad-sector
https://askubuntu.com/questions/751134/problems-restoring-damaged-sectors-on-hdd

ACME.sh使用ZeroSSL和Buypass根证书CA签发免费ssl证书

发布时间:December 25, 2020 // 分类: // No Comments

Let's Encrypt使用的DST Root CA X3根证书即将过期,而新根证书ISRG Root X1签发于2015年较新不被老设备信任,acme.sh最新版本支持zerossl和buypass签发证书,zerossl和buypass的根证书签发于2010年,相对支持的设备更多,申请方法:
安装acme.sh,先升级acme.sh到最新版本:

acme.sh --upgrade

通过acme.sh申请zerossl免费证书,首先在zerossl官网注册账号并生成eab-kid和eab-hmac-key:
2020-12-25_083036.jpg

acme.sh注册zerossl:

acme.sh --register-account --server zerossl --eab-kid xxxxxxx --eab-hmac-key xxxxx  

指定server为zerossl申请ssl证书:

acme.sh --server zerossl --issue --dns dns_dp -d haiyun.me -d *.haiyun.me -k ec-256 --renew-hook "systemctl restart nginx" 

或设置默认CA为zerossl:

acme.sh --set-default-ca  --server zerossl                                                                                                                                                                                                          
acme.sh --issue --dns dns_dp -d haiyun.me -d *.haiyun.me -k ec-256 --renew-hook "systemctl restart nginx"    

acme.sh申请buypass免费ssl证书:

acme.sh --server https://api.buypass.com/acme/directory --register-account  --accountemail su@haiyun.me
acme.sh --server https://api.buypass.com/acme/directory --issue --dns dns_dp -d haiyun.me -d www.haiyun.me --renew-hook "systemctl restart nginx"    

参考:
https://ffis.me/archives/2110.html
https://luotianyi.vc/4839.html

分类
最新文章
最近回复
  • opnfense: 谢谢博主!!!解决问题了!!!我之前一直以为内置的odhcp6就是唯一管理ipv6的方式
  • liyk: 这个方法获取的IPv6大概20分钟之后就会失效,默认路由先消失,然后Global IPV6再消失
  • 海运: 不好意思,没有。
  • zongboa: 您好,請問一下有immortalwrt設定guest Wi-Fi的GUI教學嗎?感謝您。
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...
归档