Exim 在 exim.conf 中获取随机凭证

Exim getting random credential in exim.conf

我一直在尝试获取 perl 子例程值和替换以从 exim.conf 中的 randomips 子例程中获取所需的字符串部分。但是,当我使用字符串替换时,出现如下错误:

Here is what I am trying to achieve

我正在尝试用冒号拆分字符串并获得第一次出现的 "interface"。我将使用第二次出现作为“helo_data.

exim.pl

sub randomhosts {
@inet = ("x.x.x.1:hostname1.domain.com","x.x.x.2:hostname2.domain.com","x.x.x.3:hostname3.domain.com"
);

return $inet[int rand($#inet+1)];

}

exim.conf

dkim_remote_smtp:
  driver = smtp
  interface = "${perl{randomhosts}%:*}"
  helo_data = "${sender_address_domain}"

我得到的错误如下:

"failed to expand "interface" option for dkim_remote_smtp transport: missing '}' after 'perl'". 大概是语法。 有帮助吗?

首先,我想说明一下,我没有使用过 exim,所以我不能说出您到底想做什么以及为什么要这样做。

在您发布的 link 中,一个名为 'randinet' 的方法被添加到 exim.pl 并且 exim.conf 中的接口行被替换为

interface = "${perl{randinet}}"

您已经实现了一个'randomhosts'方法,并将接口行替换为

interface = "${perl{randomhosts}%:*}"

现在解析器抱怨找不到右括号。这可能是由于您可以随意添加符号,但解析器没有忽略的自由。

我建议你试试

interface = "${perl{randomhosts}}"

您试图复制的代码是由不太了解 Perl 的人编写的。它包括这一行:

return $inet[int rand($#inet+1)];

Perl 程序员会这样写

return $inet[rand @inet];

我认为这里有几个问题 - 一个与您的 Exim 语法有关,另一个与您的 Perl 语法有关。

Exim 给你这个错误:

failed to expand "interface" option for dkim_remote_smtp transport: missing '}' after 'perl'

我对从 Exim 调用 Perl 一无所知,但 this page 提到了一种语法,如 ${perl{foo}}(类似于您正在从中复制的页面中使用的语法)和一个像 ${perl{foo}{argument}} 调用子例程并向其传递参数。它没有提到像你这样的语法:

${perl{randomhosts}%:*}

我不确定您是从哪里获得该语法的,但这似乎是导致您出现第一个错误的原因。

在评论中,你说

I am stying to get first part of string before colon for each random array value for "interface" and part after colon for "helo_data"

在我看来,Exim 不支持此要求。您需要调用该函数两次才能获得所需的两条信息。您也许可以在 Perl 中使用 state 变量之类的东西来执行此操作 - 但它会比您当前拥有的代码复杂得多。

其次,您的 Perl 代码存在语法错误,因此即使 Exim 能够调用您的代码,它也无法正常工作。

您正在复制的代码设置 @inet 如下:

@inet = ("x.x.x.1", "x.x.x.2", "x.x.x.3", "x.x.x.4");

你的等效代码是这样的:

@inet = (
  "x.x.x.1:hostname1.domain.com",
  "x.x.x.2:hostname2.domain.com,
  x.x.x.3:hostname3.domain.com
 );

我重新格式化了它,使问题更加明显。您缺少数组元素周围的许多引号。 (注:我看到在我写这个答案的时候,你已经修复了。)

更新: 好的,这里有一些代码可以放入 exim.pl 中,它可以满足您的需求。

use feature qw[state];

sub randomhosts {
  state $current;

  my @inet = (
    "x.x.x.1:hostname1.domain.com",
    "x.x.x.2:hostname2.domain.com",
    "x.x.x.3:hostname3.domain.com"
  );

  if ($_[0] eq 'generate') {
    shift;
    @{$current}{qw[ip host]} = split /:/, $inet[rand @inet];
  }

  return $current->{$_[0]};
}

如果它的第一个参数是 'generate',它会生成一个新的 ip/host 对。然后它将 return 来自生成的对的主机名或 ip 地址。我想你可以像这样从你的 Exim 配置文件中调用它:

dkim_remote_smtp:
  driver = smtp
  interface = "${perl{randomhosts}{generate}{ip}}"
  helo_data = "${perl{randomhosts}{host}}"

但我不是 Exim 专家,因此语法可能需要调整。