LUKS2 확장 방법

LUKS2 확장 방법

몇 년 전에 LUKS1이 데이터 손실 없이 오른쪽과 인접한 여유 공간으로 확장하는 방법에 대한 가이드를 읽었지만 떠날 수는 없었습니다. 요즘 LUKS2에는 많은 새로운 기능이 추가되었습니다. 데이터 손실 없이 왼쪽 확장 기능을 다르게 만들 수 있나요??

답변1

tl;dr실제로는 가능하지 않습니다. 아직은 그렇습니다. 메타데이터 형식은 실행 가능해야 한다고 제안하지만 아직까지 실제로 구현되지는 않았습니다. 따라서 오래된 "모든 데이터 재배치" 또는 "새 파티션을 생성하고 LVM이 이에 대해 걱정하도록 두십시오"를 고수해야 합니다. LUKS1 및 대부분의 파일 시스템에서 수행하는 작업과 동일합니다.


그만큼LUKS2 헤더의 개념을 갖고 있다데이터 세그먼트:

Segments 객체에는 사용자 데이터(LUKS1에서 사용자 데이터 페이로드로 언급됨)가 포함된 디스크의 암호화된 영역에 대한 정의가 포함되어 있습니다. 일반 LUKS 장치의 경우 데이터 세그먼트가 하나만 존재합니다.

데이터 재암호화 시 데이터 영역은 내부적으로 신규 키와 기존 키에 따라 구분되지만, 추상화된 영역 하나만 사용자에게 제시되어야 합니다.

와 함께데이터 세그먼트, LUKS 헤더를 왼쪽으로 이동하고 원래 데이터(첫 번째 세그먼트)를 계속 가리키며 여유 공간(헤더와 데이터 세그먼트 사이)을 새 데이터 세그먼트로 사용하여 논리적으로 끝에 추가할 수 있어야 합니다. 암호화 장치. LVM이 임의의 물리적 범위 그룹을 논리 볼륨에 추가하는 방법과 같습니다.

그러나 그것은 단지 이론일 뿐이다.

아직까지는 이 기능을 구현하는 실제 사용/도구가 없으며 그렇게 할 계획이 있는지 전혀 모르겠습니다.


나는 그것이 색다른 방식(개념 증명, 일종의)으로 작동하도록 노력했습니다.

# truncate -s 100M foobar.img
# cryptsetup luksFormat --type=luks2 foobar.img
# cryptsetup luksOpen foobar.img foobar
# yes > /dev/mapper/foobar
# sync
# hexdump -C /dev/mapper/foobar
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
05400000

LUKS2 암호화된 예 패턴입니다. 데이터 세그먼트는 어떤가요?

# cryptsetup luksDump foobar.img
Data segments:
  0: crypt
    offset: 16777216 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]
# strings -n 100 foobar.img
"segments":{"0":{"type":"crypt","offset":"16777216","iv_tweak":"0","size":"dynamic","encryption":"aes-xts-plain64","sector_size":512}}

후자는 실제로 원시 LUKS2 메타데이터의 모습입니다. 이는 JSON 형식입니다. 나중에 수정하겠습니다...

그것을 키우자 - 왼쪽으로(100M씩):

# truncate -s 100M barfoo.img
# cat foobar.img >> barfoo.img
# ls -lh *.img
-rw-r--r-- 1 root root 200M Jun  9 20:57 barfoo.img
-rw-r--r-- 1 root root 100M Jun  9 20:53 foobar.img

따라서 barfoo.img는 100M의 새로운 빈 공간과 100M의 원래 LUKS 컨테이너입니다.

LUKS 헤더를 장치의 새로운 시작 부분으로 재배치합니다.

# dd bs=1M count=16 if=foobar.img of=barfoo.img conv=notrunc
# cryptsetup luksOpen barfoo.img barfoo
# hexdump -C -n 16 /dev/mapper/barfoo
00000000  4e a6 39 e7 e0 e8 63 ae  81 72 29 81 5f 1b 08 c2  |N.9...c..r)._...|
00000010

지금은 열 수 있지만데이터 세그먼트여전히 이전 오프셋(16MiB)을 가리키지만 물론 거기에 없습니다. 이에 대한 오프셋을 위해 100M을 추가했습니다.데이터 세그먼트이제 116MiB가 되어야 합니다.

편집하세요(오프셋 16777216에서 오프셋 121634816으로):

# strings -n 100 barfoo.img | head -n 1 > barfoo.json
# nano -w barfoo.json
# dd if=barfoo.json of=barfoo.img bs=1 seek=4096 conv=notrunc
# dd if=barfoo.json of=barfoo.img bs=1 seek=20480 conv=notrunc

결과:

# cryptsetup luksDump barfoo.img
Device barfoo.img is not a valid LUKS device.

아, 물론이죠. LUKS2에는 이제 메타데이터 체크섬도 있습니다. nano로 내용을 편집하고 dd로 헤더를 엉망으로 만드는 것을 원하지 않습니다. 당신을 위한 비전 마법은 없습니다, 선생님. 글쎄요, 체크섬을 패치하기 전까지는 말이죠...

# cryptsetup luksDump barfoo.img --debug
# LUKS2 header version 2 of size 16384 bytes, checksum sha256.
# Checksum:8552bf514ab70b53e63180e9fdd3bb59db1385e3dca87f792f8197b33b851aa1 (on-disk)
# Checksum:e6f322921feae0193bcbc4cddc23b87b7f192266b4a2ef34847580fd7ca18a3e (in-memory)
# LUKS2 header checksum error (offset 0).

...기본적으로 여기에서 온디스크 체크섬을 메모리 내 체크섬으로 대체합니다.

# echo e6f322921feae0193bcbc4cddc23b87b7f192266b4a2ef34847580fd7ca18a3e |
  xxd -r -ps - |
  dd of=barfoo.img bs=1 seek=448 conv=notrunc

결과(현재는 실제로):

# cryptsetup luksDump barfoo.img
Data segments:
  0: crypt
    offset: 121634816 [bytes]
    length: (whole device)
    cipher: aes-xts-plain64
    sector: 512 [bytes]
# hexdump -C /dev/mapper/barfoo
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
05400000

이 시점에서 우리는 LUKS 헤더를 왼쪽으로 100M 성공적으로 이동했습니다. 하지만 장치 크기는 여전히 동일합니다. 이제 다른 데이터 세그먼트를 추가할 수 있습니까? 오프셋 16M에서 116M까지 무료 100M 세그먼트가 있습니다. JSON에 추가해 보겠습니다.

# nano -w barfoo.json
man this is unreadable
# jq < barfoo.json > barfoo.pretty
# nano -w barfoo.pretty
...
  "segments": {
    "0": {
      "type": "crypt",
      "offset": "121634816",
      "iv_tweak": "0",
      "size": "88080384",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    },
    "1": {
      "type": "crypt",
      "offset": "16777216",
      "iv_tweak": "172032",
      "size": "104857600",
      "encryption": "aes-xts-plain64",
      "sector_size": 512
    }
  },
  "digests": {
    "0": {
      "type": "pbkdf2",
      "keyslots": [
        "0"
      ],
      "segments": [
        "0",
        "1"
      ],
...and so on and so forth...

결과:

# cryptsetup luksDump barfoo.img
Data segments:
  0: crypt
    offset: 121634816 [bytes]
    length: 88080384 [bytes]
    cipher: aes-xts-plain64
    sector: 512 [bytes]

  1: crypt
    offset: 16777216 [bytes]
    length: 104857600 [bytes]
    cipher: aes-xts-plain65
    sector: 512 [bytes]

불행하게도 이 시점에서는 장치가 제대로 열리고 크기가 올바르게 증가했지만(YAY!) 데이터가 잘못되었습니다(NOO!). 논리적 바이트 0은 예상된 116MiB 대신 물리적 바이트 16MiB에 매핑되었습니다.

야, 그건 0부가 아니라 1부야, 멍청한 빌리야! 무엇이 잘못되었나요?

모르겠습니다. 아직 아무도 테스트하지 않은 숨겨진 기능을 잠금 해제하기 위해 간단한 메타데이터 수정을 수행해서는 안 되는 것과 거의 같습니다.

제가 이해가 부족한 탓인지 세그먼트를 반대 방향으로 배치해도 계속 잘못된 순서로 열리게 됩니다. 물리적인 오프셋을 기준으로 뭔가를 정렬하고 있나요? 그런데 왜?

그래서 불행하게도 이 특별한 마법은 실패로 끝났습니다. 내가 뭔가 잘못했기 때문이거나 아직 사용할 준비가 되지 않았기 때문입니다. 그래도 기능은 어느 정도 존재하므로 미래에 대한 희망은 여전히 ​​남아 있습니다.

작동하더라도 사용하는 것이 좋지 않습니다.

관련 정보