From 17d3763d8f43932a3db27533eef7d5f5e985e5b5 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 8 Aug 2024 12:10:53 +0300 Subject: [PATCH 1/6] given private network default to SPF neutral --- lib/auth.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/auth.js b/lib/auth.js index 2fc7116..68d5a71 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -23,14 +23,24 @@ async function hookMail(plugin, connection, params) { let spfResult; try { + const isRemotePrivate = connection.remote.is_private; + spfResult = await checkSpf({ resolver: plugin.resolver, - ip: connection.remote.ip, // SMTP client IP + ip: isRemotePrivate ? undefined : connection.remote.ip, // SMTP client IP (undefined for if remote is private network) helo: connection.hello?.host, // EHLO/HELO hostname sender: txn.notes.sender, // MAIL FROM address mta: connection.local?.host, // MX hostname maxResolveCount: plugin.cfg?.auth?.dns?.maxLookups }); + + if (isRemotePrivate) { + // given undefined client ip verification will by default return neutral SPF result, replace 'undefined' with the IP + spfResult.status.comment = spfResult.status.comment.replaceAll('undefined', connection.remote.ip); + spfResult.header = spfResult.header.replaceAll('undefined', connection.remote.ip); + spfResult.info = spfResult.header.replaceAll('undefined', connection.remote.ip); + } + txn.notes.spfResult = spfResult; } catch (err) { txn.notes.spfResult = { error: err }; From 23f059615e1a0bfd325e782007d8f9b48d6d0bb4 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 8 Aug 2024 12:33:25 +0300 Subject: [PATCH 2/6] change neutral to softfail, add custom message --- lib/auth.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/auth.js b/lib/auth.js index 68d5a71..cccbb8f 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -36,9 +36,10 @@ async function hookMail(plugin, connection, params) { if (isRemotePrivate) { // given undefined client ip verification will by default return neutral SPF result, replace 'undefined' with the IP - spfResult.status.comment = spfResult.status.comment.replaceAll('undefined', connection.remote.ip); - spfResult.header = spfResult.header.replaceAll('undefined', connection.remote.ip); - spfResult.info = spfResult.header.replaceAll('undefined', connection.remote.ip); + spfResult.status.result = 'softfail'; + spfResult.status.comment = 'cannot assess local addresses'; + spfResult.header = `Received-SPF: softfail (cannot assess local addresses) client-ip=${connection.remote.ip};`; + spfResult.info = `spf=softfail (cannot assess local addresses)`; } txn.notes.spfResult = spfResult; From 3355d0c5d5ce38b33297f0f8085e375da0a62089 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Thu, 8 Aug 2024 12:38:17 +0300 Subject: [PATCH 3/6] fix comment --- lib/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/auth.js b/lib/auth.js index cccbb8f..b98ecaa 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -35,7 +35,7 @@ async function hookMail(plugin, connection, params) { }); if (isRemotePrivate) { - // given undefined client ip verification will by default return neutral SPF result, replace 'undefined' with the IP + // given undefined IP as client IP in case client is from remote IP, SPF will default to neutral, replace with softfail and custom message spfResult.status.result = 'softfail'; spfResult.status.comment = 'cannot assess local addresses'; spfResult.header = `Received-SPF: softfail (cannot assess local addresses) client-ip=${connection.remote.ip};`; From 8634c4dae55abb9092ada9f53eaa1f34e75221fc Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Wed, 14 Aug 2024 10:12:11 +0300 Subject: [PATCH 4/6] Add workflow to build and push the docker image to GHCR on repo release --- .github/workflows/docker-release.yaml | 52 +++++++++++++++++++++++++++ Dockerfile | 22 ++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 .github/workflows/docker-release.yaml create mode 100644 Dockerfile diff --git a/.github/workflows/docker-release.yaml b/.github/workflows/docker-release.yaml new file mode 100644 index 0000000..336857f --- /dev/null +++ b/.github/workflows/docker-release.yaml @@ -0,0 +1,52 @@ +name: Create and publish a Docker image + +on: + release: + types: [published] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + attestations: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..be8e7cd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM node:lts-alpine as builder + +RUN apk add --no-cache git python3 py3-pip make g++ + +WORKDIR /app + +RUN git clone https://github.com/haraka/Haraka.git ./ --branch master +RUN npm install --production +RUN npm install haraka-plugin-wildduck + + +FROM node:lts-alpine as app + +ENV NODE_ENV production + +RUN apk add --no-cache tini +RUN apk add --no-cache openssl + +WORKDIR /app +COPY --from=builder /app /app + +ENTRYPOINT ["/sbin/tini", "--", "node", "haraka.js"] From 5b4d1b3b7d10fe2801b4f2a8dfefcf444e3c6205 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Mon, 9 Sep 2024 11:01:38 +0300 Subject: [PATCH 5/6] github action version fix. Dockerfile fixes --- .github/workflows/docker-release.yaml | 2 +- Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-release.yaml b/.github/workflows/docker-release.yaml index 336857f..a3c3024 100644 --- a/.github/workflows/docker-release.yaml +++ b/.github/workflows/docker-release.yaml @@ -37,7 +37,7 @@ jobs: - name: Build and push Docker image id: push - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: true diff --git a/Dockerfile b/Dockerfile index be8e7cd..d25a4fd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,6 @@ RUN git clone https://github.com/haraka/Haraka.git ./ --branch master RUN npm install --production RUN npm install haraka-plugin-wildduck - FROM node:lts-alpine as app ENV NODE_ENV production @@ -19,4 +18,5 @@ RUN apk add --no-cache openssl WORKDIR /app COPY --from=builder /app /app -ENTRYPOINT ["/sbin/tini", "--", "node", "haraka.js"] +ENTRYPOINT ["/sbin/tini", "--"] +CMD ["node", "index.js"] From 25d2c6f6a942f72a70d41d1647ecae92c0b1bfd1 Mon Sep 17 00:00:00 2001 From: Nikolai Ovtsinnikov Date: Mon, 9 Sep 2024 12:20:50 +0300 Subject: [PATCH 6/6] github actions. Add qemu, add tags (semver), add platforms --- .github/workflows/docker-release.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/docker-release.yaml b/.github/workflows/docker-release.yaml index a3c3024..309401f 100644 --- a/.github/workflows/docker-release.yaml +++ b/.github/workflows/docker-release.yaml @@ -22,6 +22,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: 'arm64,arm' + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/arm64,linux/amd64,linux/arm/v7 + - name: Log in to the Container registry uses: docker/login-action@v3 with: @@ -34,6 +45,11 @@ jobs: uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=tag + type=semver,pattern={{major}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{version}} - name: Build and push Docker image id: push @@ -41,6 +57,7 @@ jobs: with: context: . push: true + platforms: ${{ steps.buildx.outputs.platforms }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}