diff -dru libalias.orig/alias_db.c libalias/alias_db.c --- libalias.orig/alias_db.c 2019-06-30 08:54:24.823944000 +0200 +++ libalias/alias_db.c 2019-06-30 09:59:38.345534000 +0200 @@ -2676,7 +2676,12 @@ { ipfw_insn_u16 *cmd = (ipfw_insn_u16 *) cmd1; - cmd->ports[0] = cmd->ports[1] = port; + if (port == 0) { + cmd->ports[0] = 1024; + cmd->ports[1] = 65535; + } else { + cmd->ports[0] = cmd->ports[1] = port; + } return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0); } @@ -2753,6 +2758,12 @@ void PunchFWHole(struct alias_link *lnk) { + PunchFWHolePorts(lnk, 0); +} + +void +PunchFWHolePorts(struct alias_link *lnk, int oport_zero_ok) +{ struct libalias *la; int r; /* Result code */ struct ip_fw rule; /* On-the-fly built rule */ @@ -2798,7 +2809,7 @@ * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole * accept tcp from DAddr DPort to OAddr OPort */ - if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) { + if ((oport_zero_ok || GetOriginalPort(lnk) != 0) && GetDestPort(lnk) != 0) { u_int32_t rulebuf[255]; int i; diff -dru libalias.orig/alias_ftp.c libalias/alias_ftp.c --- libalias.orig/alias_ftp.c 2019-06-30 08:54:24.466592000 +0200 +++ libalias/alias_ftp.c 2019-06-30 09:59:08.669920000 +0200 @@ -312,18 +312,41 @@ * properly terminated with CRLF. */ pflags = GetProtocolFlags(lnk); - if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0 && - ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER && - (ParseFtpPortCommand(la, sptr, dlen) != 0 || - ParseFtpEprtCommand(la, sptr, dlen) != 0)) { - /* - * Alias active mode client requesting data from server - * behind NAT. We need to alias server->client connection - * to external address client is connecting to. - */ - AddLink(la, GetOriginalAddress(lnk), la->true_addr, - GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1), - htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP); + if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0) { + int ftp_message_type = FTP_UNKNOWN_MESSAGE; + + if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) { + if (ParseFtpPortCommand(la, sptr, dlen) != 0 || + ParseFtpEprtCommand(la, sptr, dlen) != 0) { + /* + * Alias active mode client requesting data from server + * behind NAT. We need to alias server->client connection + * to external address client is connecting to. + */ + AddLink(la, GetOriginalAddress(lnk), la->true_addr, + GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1), + htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP); + } + } else if (ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) { + if (ParseFtp227Reply(la, sptr, dlen)) + ftp_message_type = FTP_227_REPLY; + else if (ParseFtp229Reply(la, sptr, dlen)) { + ftp_message_type = FTP_229_REPLY; + la->true_addr.s_addr = pip->ip_src.s_addr; + } + } + + if (ftp_message_type != FTP_UNKNOWN_MESSAGE) { + struct alias_link *ftp_lnk; + + ftp_lnk = AddLink(la, GetOriginalAddress(lnk), la->true_addr, + GetAliasAddress(lnk), 0, htons(la->true_port), + GET_ALIAS_PORT, IPPROTO_TCP); +#ifndef NO_FW_PUNCH + if (ftp_lnk != NULL) + PunchFWHolePorts(ftp_lnk, 1); +#endif + } } /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */ if (dlen) { diff -dru libalias.orig/alias_local.h libalias/alias_local.h --- libalias.orig/alias_local.h 2019-06-30 08:54:24.763905000 +0200 +++ libalias/alias_local.h 2019-06-30 09:31:01.182183000 +0200 @@ -358,6 +358,7 @@ void SetDestCallId(struct alias_link *_lnk, u_int16_t _cid); #ifndef NO_FW_PUNCH +void PunchFWHolePorts(struct alias_link *lnk, int oport_zero_ok); void PunchFWHole(struct alias_link *_lnk); #endif