LUKS2를 확장하는 방법

LUKS2를 확장하는 방법

몇 년 전에 LUKS1이 데이터 손실 없이 오른쪽과 인접한 여유 공간으로 확장할 수 있는 방법에 대한 가이드를 읽었지만 빠져나오지 못했습니다. 이제 많은 새로운 기능을 제공하는 LUKS2가 출시되었으므로 데이터 손실 없이 왼쪽 확장을 다르게 만드는 것이 가능합니까?

답변1

너무 길어요.그럴 가능성은 거의 없습니다. 아직은 아닙니다. 메타데이터 형식에서는 이것이 가능하다고 제안하지만 지금까지는 실제로 구현되지 않았습니다. 따라서 오래된 "모든 데이터 재배치" 또는 "새 파티션을 생성하고 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]

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

야, 그건 0이 아니라 1이야, 이 바보 같은 빌리! 무엇이 잘못되었나요?

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

제가 이해력이 부족한 탓인지, 조각을 반대로 배치해도 여전히 잘못된 순서로 열립니다. 물리적 오프셋을 기준으로 정렬하는 것이 있나요? 그런데 왜?

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

작동하더라도 권장되지는 않습니다.

관련 정보