Compare commits
No commits in common. "master" and "pristine-tar" have entirely different histories.
master
...
pristine-t
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
*.pl linguist-language=C
|
|
||||||
*.pm linguist-language=C
|
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
*.swp
|
|
32
.travis.yml
32
.travis.yml
@ -1,32 +0,0 @@
|
|||||||
language: c
|
|
||||||
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
|
|
||||||
install:
|
|
||||||
# for unit tests
|
|
||||||
- sudo apt-get install -y check
|
|
||||||
- sudo apt-get install -y libsubunit-dev
|
|
||||||
# for static code analysis
|
|
||||||
# - sudo apt-get install -y cppcheck
|
|
||||||
# - sudo apt-get install -y rats
|
|
||||||
# for test code coverage
|
|
||||||
- sudo apt-get install -y lcov
|
|
||||||
- gem install coveralls-lcov
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- cd ${TRAVIS_BUILD_DIR}
|
|
||||||
- lcov --directory . --zerocounters
|
|
||||||
|
|
||||||
script:
|
|
||||||
# - find . -type f -name "*.c" -print | grep -v t\/ | xargs cppcheck 2>&1
|
|
||||||
# - find . -type f -name "*.c" -print | grep -v t\/ | xargs rats --language=c
|
|
||||||
- git clone --depth 10 https://github.com/proftpd/proftpd.git
|
|
||||||
- cp mod_proxy_protocol.c proftpd/contrib/
|
|
||||||
- cd proftpd
|
|
||||||
- ./configure LIBS="-lm -lsubunit -lrt -pthread" --enable-devel=coverage --enable-tests --with-module=mod_proxy_protocol
|
|
||||||
- make
|
|
||||||
- make clean
|
|
||||||
- ./configure LIBS="-lm -lsubunit -lrt -pthread" --enable-devel=coverage --enable-dso --enable-tests --with-shared=mod_proxy_protocol
|
|
||||||
- make
|
|
15
README.md
15
README.md
@ -1,15 +0,0 @@
|
|||||||
proftpd-mod_proxy_protocol
|
|
||||||
==========================
|
|
||||||
|
|
||||||
Status
|
|
||||||
------
|
|
||||||
[![Build Status](https://travis-ci.org/Castaglia/proftpd-mod_proxy_protocol.svg?branch=master)](https://travis-ci.org/Castaglia/proftpd-mod_proxy_protocol)
|
|
||||||
[![License](https://img.shields.io/badge/license-GPL-brightgreen.svg)](https://img.shields.io/badge/license-GPL-brightgreen.svg)
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
The `mod_proxy_protocol` module for ProFTPD handles protocols that are used
|
|
||||||
for conveying connection information via proxies such as <code>haproxy</code>.
|
|
||||||
|
|
||||||
See the [mod_proxy_protocol.html](https://htmlpreview.github.io/?https://github.com/Castaglia/proftpd-mod_proxy_protocol/blob/master/mod_proxy_protocol.html) documentation for more details.
|
|
13
debian/changelog
vendored
13
debian/changelog
vendored
@ -1,13 +0,0 @@
|
|||||||
proftpd-mod-proxy-protocol (0.2-1) UNRELEASED; urgency=medium
|
|
||||||
|
|
||||||
* Update build
|
|
||||||
* Bump to new release
|
|
||||||
|
|
||||||
-- Mario Fetka <mario.fetka@gmail.com> Wed, 11 Mar 2020 11:40:24 +0100
|
|
||||||
|
|
||||||
proftpd-mod-proxy-protocol (0.1-1) unstable; urgency=low
|
|
||||||
|
|
||||||
[ Fabrizio Regalli ]
|
|
||||||
* Initial Release. (Closes: #623228)
|
|
||||||
|
|
||||||
-- Francesco Paolo Lovergine <frankie@debian.org> Tue, 11 Oct 2011 12:29:18 +0200
|
|
1
debian/compat
vendored
1
debian/compat
vendored
@ -1 +0,0 @@
|
|||||||
9
|
|
21
debian/control
vendored
21
debian/control
vendored
@ -1,21 +0,0 @@
|
|||||||
Source: proftpd-mod-proxy-protocol
|
|
||||||
Section: net
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: ProFTPD Maintainance Team <pkg-proftpd-maintainers@alioth-lists.debian.net>
|
|
||||||
Uploaders: Francesco Paolo Lovergine <frankie@debian.org>
|
|
||||||
Build-Depends: debhelper (>= 9.20120909), proftpd-dev (>= 1.3.3~)
|
|
||||||
Standards-Version: 4.1.4
|
|
||||||
Homepage: http://www.castaglia.org/proftpd/modules/mod_proxy_protocol.html
|
|
||||||
Vcs-Browser: https://salsa.debian.org/debian-proftpd-team/proftpd-mod-proxy-protocol
|
|
||||||
Vcs-Git: https://salsa.debian.org/debian-proftpd-team/proftpd-mod-proxy-protocol.git
|
|
||||||
|
|
||||||
Package: proftpd-mod-proxy-protocol
|
|
||||||
Architecture: any
|
|
||||||
Depends: proftpd-basic (>= 1.3.3d-4~), ${misc:Depends}, ${shlibs:Depends}, ${proftpd:Depends}
|
|
||||||
Description: ProFTPD module mod_proxy-protocol
|
|
||||||
The mod_proxy-protocol module attempts to prevent such bottlenecks by forcibly
|
|
||||||
flushing to disk the buffers used for files open for writing after a
|
|
||||||
certain number of bytes have been written (for example, after 128 KB
|
|
||||||
has been written to a file). This prevents the buffer cache from being
|
|
||||||
dominated by data from files being written, freeing up space for data
|
|
||||||
for files being read.
|
|
30
debian/copyright
vendored
30
debian/copyright
vendored
@ -1,30 +0,0 @@
|
|||||||
Format: http://dep.debian.net/deps/dep5/
|
|
||||||
Upstream-Name: mod_proxy_protocol
|
|
||||||
Upstream-Contact: TJ Saunders
|
|
||||||
Source: http://www.castaglia.org/proftpd/modules/mod_proxy_protocol.html
|
|
||||||
|
|
||||||
Files: *
|
|
||||||
Copyright: 2007-2010, TJ Saunders
|
|
||||||
License: GPL-2+
|
|
||||||
|
|
||||||
License: GPL-2+
|
|
||||||
This package is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
.
|
|
||||||
This package is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
.
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
.
|
|
||||||
On Debian systems, the complete text of the GNU General
|
|
||||||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
|
||||||
|
|
||||||
Files: debian/*
|
|
||||||
Copyright: 2011, Fabrizio Regalli <fabreg@fabreg.it>
|
|
||||||
License: GPL-2+
|
|
||||||
|
|
2
debian/proftpd-mod-proxy-protocol.dirs
vendored
2
debian/proftpd-mod-proxy-protocol.dirs
vendored
@ -1,2 +0,0 @@
|
|||||||
usr/lib/proftpd
|
|
||||||
usr/share/proftpd/templates
|
|
9
debian/proftpd-mod-proxy-protocol.doc-base
vendored
9
debian/proftpd-mod-proxy-protocol.doc-base
vendored
@ -1,9 +0,0 @@
|
|||||||
Document: proftpd-mod-proxy-protocol
|
|
||||||
Title: Documentation for the mod_msg ProFTPD
|
|
||||||
Author:
|
|
||||||
Abstract: Configuration reference, modules documentation, FAQs and HOWTOs
|
|
||||||
Section: System/Administration
|
|
||||||
|
|
||||||
Format: HTML
|
|
||||||
Index: /usr/share/doc/proftpd-mod-proxy-protocol/mod_proxy_protocol.html
|
|
||||||
Files: /usr/share/doc/proftpd-mod-proxy-protocol/*.html
|
|
2
debian/proftpd-mod-proxy-protocol.docs
vendored
2
debian/proftpd-mod-proxy-protocol.docs
vendored
@ -1,2 +0,0 @@
|
|||||||
README.md
|
|
||||||
mod_proxy_protocol.html
|
|
1
debian/proftpd-mod-proxy-protocol.install
vendored
1
debian/proftpd-mod-proxy-protocol.install
vendored
@ -1 +0,0 @@
|
|||||||
debian/templates/proxy_protocol.conf usr/share/doc/proftpd-mod-proxy-protocol/
|
|
1
debian/proftpd-mod-proxy-protocol.links
vendored
1
debian/proftpd-mod-proxy-protocol.links
vendored
@ -1 +0,0 @@
|
|||||||
usr/share/doc/proftpd-mod-proxy-protocol/proxy-protocol.conf usr/share/proftpd/templates/proxy-protocol.conf
|
|
24
debian/rules
vendored
24
debian/rules
vendored
@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
# -*- makefile -*-
|
|
||||||
|
|
||||||
export DH_VERBOSE=1
|
|
||||||
VERSION=$(shell grep PROFTPD_VERSION_TEXT /usr/include/proftpd/version.h|cut -d\" -f2)
|
|
||||||
MODULE_NAME=mod_proxy_protocol
|
|
||||||
DEBNAME=proftpd-mod-proxy-protocol
|
|
||||||
CFLAGS := -Wno-implicit-function-declaration
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@ --without python-support
|
|
||||||
|
|
||||||
override_dh_auto_build:
|
|
||||||
DESTDIR=$(CURDIR)/debian/$(DEBNAME) CFLAGS=$(CFLAGS) prxs -c $(MODULE_NAME).c
|
|
||||||
|
|
||||||
override_dh_auto_install:
|
|
||||||
DESTDIR=$(CURDIR)/debian/$(DEBNAME) CFLAGS=$(CFLAGS) prxs -i -c $(MODULE_NAME).c
|
|
||||||
|
|
||||||
override_dh_gencontrol:
|
|
||||||
cat /usr/share/proftpd/proftpd-substvars >>$(CURDIR)/debian/$(DEBNAME).substvars
|
|
||||||
dh_gencontrol
|
|
||||||
|
|
||||||
override_dh_auto_clean:
|
|
||||||
DESTDIR=$(CURDIR)/debian/$(DEBNAME) CFLAGS=$(CFLAGS) prxs -d $(MODULE_NAME).c
|
|
1
debian/source/format
vendored
1
debian/source/format
vendored
@ -1 +0,0 @@
|
|||||||
3.0 (quilt)
|
|
20
debian/templates/proxy_protocol.conf
vendored
20
debian/templates/proxy_protocol.conf
vendored
@ -1,20 +0,0 @@
|
|||||||
#
|
|
||||||
# Proftpd sample configuration for mod_fsync.
|
|
||||||
<IfModule mod_proxy_protocol.c>
|
|
||||||
#The ProxyProtocolEngine directive enables the
|
|
||||||
#expectation and handling of protocols which provide
|
|
||||||
#information on proxied connections; support for these
|
|
||||||
#protocols is provided by mod_proxy_protocol.
|
|
||||||
ProxyProtocolEngine on
|
|
||||||
|
|
||||||
#The ProxyProtocolTimeout directive is used to configure
|
|
||||||
#the amount of time, in seconds, that mod_proxy_protocol
|
|
||||||
#will wait to receive the full expected proxy information.
|
|
||||||
#If the full information is not received within the given
|
|
||||||
#number of seconds, the connection to the client is closed.
|
|
||||||
ProxyProtocolTimeout 3sec
|
|
||||||
|
|
||||||
# Necessary to allow data transfers
|
|
||||||
AllowForeignAddress on
|
|
||||||
|
|
||||||
</IfModule>
|
|
2
debian/watch
vendored
2
debian/watch
vendored
@ -1,2 +0,0 @@
|
|||||||
version=3
|
|
||||||
http://www.castaglia.org/proftpd/modules/proftpd-mod-fsync-([\d\.]+)\.tar\.gz
|
|
1185
mod_proxy_protocol.c
1185
mod_proxy_protocol.c
File diff suppressed because it is too large
Load Diff
@ -1,257 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>ProFTPD module mod_proxy_protocol</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor=white>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<center>
|
|
||||||
<h2><b>ProFTPD module <code>mod_proxy_protocol</code></b></h2>
|
|
||||||
</center>
|
|
||||||
<hr><br>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The purpose of the <code>mod_proxy_protocol</code> module is to handle
|
|
||||||
protocols which are used by proxies, <i>e.g.</i> <code>haproxy</code>, for
|
|
||||||
conveying information about the real origin/client to the backend server.
|
|
||||||
Protocols like HTTP often have their own mechanism for doing so, via headers
|
|
||||||
such as "X-Forwarded-For". Unfortunately, FTP does <b>not</b> have such a
|
|
||||||
mechanism, nor does SSH.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
However, there <em>are</em> protocols which an provide this information without
|
|
||||||
impacting FTP. HAproxy's <a href="http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt"><code>PROXY</code></a> protocol is one such mechanism. The
|
|
||||||
<code>mod_proxy_protocol</code> module uses these mechanisms to change the
|
|
||||||
information about the "remote" client so that it is the real client, not the
|
|
||||||
proxy, whose IP address/port are logged and used for <i>e.g.</i> network ACLs.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This module is contained in the <code>mod_proxy_protocol.c</code> file for
|
|
||||||
ProFTPD 1.3.<i>x</i>, and is not compiled by default. Installation
|
|
||||||
instructions are discussed <a href="#Installation">here</a>; detailed
|
|
||||||
notes on best practices for using this module are <a href="#Usage">here</a>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The most current version of <code>mod_proxy_protocol</code> can be found at:
|
|
||||||
<pre>
|
|
||||||
<a href="https://github.com/Castaglia/proftpd-mod_proxy_protocol.git">https://github.com/Castaglia/proftpd-mod_proxy_protocol.git</a>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h2>Author</h2>
|
|
||||||
<p>
|
|
||||||
Please contact TJ Saunders <tj <i>at</i> castaglia.org> with any
|
|
||||||
questions, concerns, or suggestions regarding this module.
|
|
||||||
|
|
||||||
<h2>Directives</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#ProxyProtocolEngine">ProxyProtocolEngine</a>
|
|
||||||
<li><a href="#ProxyProtocolTimeout">ProxyProtocolTimeout</a>
|
|
||||||
<li><a href="#ProxyProtocolVersion">ProxyProtocolVersion</a>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="ProxyProtocolEngine">ProxyProtocolEngine</a></h2>
|
|
||||||
<strong>Syntax:</strong> ProxyProtocolEngine <em>on|off</em><br>
|
|
||||||
<strong>Default:</strong> None<br>
|
|
||||||
<strong>Context:</strong> server config, <code><VirtualHost></code>, <code><Global></code><br>
|
|
||||||
<strong>Module:</strong> mod_proxy_protocol<br>
|
|
||||||
<strong>Compatibility:</strong> 1.3.5rc4 and later
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The <code>ProxyProtocolEngine</code> directive enables the expectation
|
|
||||||
and handling of protocols which provide information on proxied connections;
|
|
||||||
support for these protocols is provided by <code>mod_proxy_protocol</code>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="ProxyProtocolTimeout">ProxyProtocolTimeout</a></h2>
|
|
||||||
<strong>Syntax:</strong> ProxyProtocolTimeout <em>seconds</em><br>
|
|
||||||
<strong>Default:</strong> 3sec<br>
|
|
||||||
<strong>Context:</strong> server config, <code><VirtualHost></code>, <code><Global></code><br>
|
|
||||||
<strong>Module:</strong> mod_proxy_protocol<br>
|
|
||||||
<strong>Compatibility:</strong> 1.3.5rc4 and later
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The <code>ProxyProtocolTimeout</code> directive is used to configure the
|
|
||||||
amount of time, in seconds, that <code>mod_proxy_protocol</code> will wait to
|
|
||||||
receive the full expected proxy information. If the full information is
|
|
||||||
not received within the given number of seconds, the connection to the client
|
|
||||||
is closed.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="ProxyProtocolVersion">ProxyProtocolVersion</a></h2>
|
|
||||||
<strong>Syntax:</strong> ProxyProtocolVersion <em>protocolVersion</em><br>
|
|
||||||
<strong>Default:</strong> haproxyV1<br>
|
|
||||||
<strong>Context:</strong> server config, <code><VirtualHost></code>, <code><Global></code><br>
|
|
||||||
<strong>Module:</strong> mod_proxy_protocol<br>
|
|
||||||
<strong>Compatibility:</strong> 1.3.5rc4 and later
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The <code>ProxyProtocolVersion</code> directive is used to configure the
|
|
||||||
protocol that <code>mod_proxy_protocol</code> expects to handle. The
|
|
||||||
currently supported values are:
|
|
||||||
<ul>
|
|
||||||
<li><code>haproxyV1</code>
|
|
||||||
<li><code>haproxyV2</code>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="Usage">Usage</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Example Configuration</b><br>
|
|
||||||
<pre>
|
|
||||||
<IfModule mod_proxy_protocol.c>
|
|
||||||
ProxyProtocolEngine on
|
|
||||||
ProxyProtocolTimeout 3sec
|
|
||||||
|
|
||||||
# Necessary to allow data transfers
|
|
||||||
AllowForeignAddress on
|
|
||||||
</IfModule>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Module Load Order</b><br>
|
|
||||||
In order for <code>mod_proxy_protocol</code> to work its magic, it <b>must</b>
|
|
||||||
the first module in line to handle the bytes coming in from the client.
|
|
||||||
If some other module (such as <code>mod_sftp</code> or <code>mod_tls</code>)
|
|
||||||
tries to handle the incoming bytes first, Bad Things will happen, since those
|
|
||||||
modules will expect different protocols than the <code>PROXY</code> protocol.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For <code>mod_proxy_protocol</code> to be the first module called, it must
|
|
||||||
the <b>last</b> module loaded. To do this as a static module, you would
|
|
||||||
use something like this when building proftpd:
|
|
||||||
<pre>
|
|
||||||
# ./configure --with-modules=...:mod_proxy_protocol
|
|
||||||
</pre>
|
|
||||||
ensuring that <code>mod_proxy_protocol</code> is the <b>last</b> module in
|
|
||||||
your <code>--with-modules</code> list.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
As a shared module, configuring <code>mod_proxy_protocol</code> to be the
|
|
||||||
last module loaded is much easier. Your configuration will have a list
|
|
||||||
of <code>LoadModule</code> directives; the last of which would be:
|
|
||||||
<pre>
|
|
||||||
LoadModule mod_proxy_protocol.c
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<b>Note</b> that using <code>mod_proxy_protocol</code> as a shared module
|
|
||||||
is <i>required</i> in cases where you want to use both
|
|
||||||
<code>mod_proxy_protocol</code> <i>and</i> <code>mod_ifsession</code>. For
|
|
||||||
example, perhaps you want to use <code>mod_ifsession</code> to change the
|
|
||||||
behavior of some module, <i>e.g.</i> <code>mod_ban</code>, based on the IP
|
|
||||||
address of the original client. This means that <code>mod_proxy_protocol</code>
|
|
||||||
would need to hande the connection <i>first</i>, so that it can decode the
|
|
||||||
<code>PROXY</code> protocol and set the correct client IP address.
|
|
||||||
<i>However</i>, the ProFTPD build system is hardcoded to ensure that the
|
|
||||||
<code>mod_ifsession</code> will always be first -- <i>if</i> using static
|
|
||||||
modules. By using <i>shared</i> modules, you can enforce the proper ordering
|
|
||||||
using the <code>LoadModule</code> directive, like so:
|
|
||||||
<pre>
|
|
||||||
<IfModule mod_dso.c>
|
|
||||||
...
|
|
||||||
LoadModule mod_ifsession.c
|
|
||||||
LoadModule mod_proxy_protocol.c
|
|
||||||
</IfModule>
|
|
||||||
</pre>
|
|
||||||
The <i>last</i> module loaded will be the <i>first</i> module called.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Trusting Senders of Proxy Data</b><br>
|
|
||||||
Use of these proxy protocols means changes in audit trails and/or client
|
|
||||||
access permissions (<i>e.g.</i> different <code>mod_wrap2</code> and/or
|
|
||||||
<code>mod_geoip</code> rules will apply). Unscrupulous senders may try to
|
|
||||||
actively lie to your server about the original client using these protocols.
|
|
||||||
Thus you <b>must</b> trust the upstream machines <b>before</b> enabling the
|
|
||||||
<code>mod_proxy_protocol</code> module.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Put another way: do <b>not</b> use the <code>mod_proxy_protocol</code> module
|
|
||||||
if your server handles connections from the open Internet. Doing so means
|
|
||||||
that any machine can use the proxy protocol to hide their activities, or
|
|
||||||
make it look like the connection is coming from someone else. <b>Only accept
|
|
||||||
proxy information from trusted sources.</b>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Why <code>AllowForeignAddress</code> Is Needed</b><br>
|
|
||||||
One of the consequences of allowing <code>mod_proxy_protocol</code> to change
|
|
||||||
the remote IP address is that security checks performed on data transfers
|
|
||||||
will cause problems. For active data transfers (<i>i.e.</i> for clients
|
|
||||||
which send the <code>PORT</code> or <code>EPRT</code> commands),
|
|
||||||
<code>proftpd</code> requires that the IP address sent in the command matches
|
|
||||||
the IP address of the client which sends the command. Otherwise, a message
|
|
||||||
like the following is logged:
|
|
||||||
<pre>
|
|
||||||
Refused PORT 127,0,0,1,218,225 (address mismatch)
|
|
||||||
</pre>
|
|
||||||
and the command is rejected.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Similarly for passive data transfers (<i>i.e.</i> for clients which send the
|
|
||||||
<code>PASV</code> or <code>EPSV</code> commands), <code>proftpd</code> requires
|
|
||||||
that the remote IP address of the client which connects to the data transfer
|
|
||||||
address <b>must</b> match the remote IP address of the client on the control
|
|
||||||
connection. If the addresses do no match, then the following is logged:
|
|
||||||
<pre>
|
|
||||||
SECURITY VIOLATION: Passive connection from 127.0.0.1 rejected.
|
|
||||||
</pre>
|
|
||||||
and the control connection is closed.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
These security measures are done to prevent abuses of FTP data transfers
|
|
||||||
such as the <a href="http://www.proftpd.org/docs/howto/FXP.html">FTP bounce</a>
|
|
||||||
attack. However, the very fact that <code>mod_proxy_protocol</code> changes
|
|
||||||
the remote IP address means that to allow data transfers when using this module,
|
|
||||||
you need to use:
|
|
||||||
<pre>
|
|
||||||
AllowForeignAddress on
|
|
||||||
</pre>
|
|
||||||
in the same virtual host section in which the <code>ProxyProtocolEngine</code>
|
|
||||||
directive appears.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="Installation">Installation</a></h2>
|
|
||||||
To install <code>mod_proxy_protocol</code>, copy the
|
|
||||||
<code>mod_proxy_protocol.c</code> file into:
|
|
||||||
<pre>
|
|
||||||
<i>proftpd-dir</i>/contrib/
|
|
||||||
</pre>
|
|
||||||
after unpacking the latest proftpd-1.3.<i>x</i> source code. For including
|
|
||||||
<code>mod_proxy_protocol</code> as a staticly linked module:
|
|
||||||
<pre>
|
|
||||||
$ ./configure --with-modules=...:mod_proxy_protocol
|
|
||||||
</pre>
|
|
||||||
To build <code>mod_proxy_protocol</code> as a DSO module:
|
|
||||||
<pre>
|
|
||||||
$ ./configure --enable-dso --with-shared=...:mod_proxy_protocol
|
|
||||||
</pre>
|
|
||||||
Then follow the usual steps:
|
|
||||||
<pre>
|
|
||||||
$ make
|
|
||||||
$ make install
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
For those with an existing ProFTPD installation, you can use the
|
|
||||||
<code>prxs</code> tool to add <code>mod_proxy_protocol</code>, as a DSO module,
|
|
||||||
to your existing server:
|
|
||||||
<pre>
|
|
||||||
$ prxs -c -i -d mod_proxy_protocol.c
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<font size=2><b><i>
|
|
||||||
© Copyright 2013-2019 TJ Saunders<br>
|
|
||||||
All Rights Reserved<br>
|
|
||||||
</i></b></font>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
BIN
proftpd-mod-proxy-protocol_0.1.orig.tar.gz.delta
Normal file
BIN
proftpd-mod-proxy-protocol_0.1.orig.tar.gz.delta
Normal file
Binary file not shown.
1
proftpd-mod-proxy-protocol_0.1.orig.tar.gz.id
Normal file
1
proftpd-mod-proxy-protocol_0.1.orig.tar.gz.id
Normal file
@ -0,0 +1 @@
|
|||||||
|
203415895161bb166026dc51bc5c6de39feed5e0
|
BIN
proftpd-mod-proxy-protocol_0.2.orig.tar.gz.delta
Normal file
BIN
proftpd-mod-proxy-protocol_0.2.orig.tar.gz.delta
Normal file
Binary file not shown.
1
proftpd-mod-proxy-protocol_0.2.orig.tar.gz.id
Normal file
1
proftpd-mod-proxy-protocol_0.2.orig.tar.gz.id
Normal file
@ -0,0 +1 @@
|
|||||||
|
3ec657c149e5483defdbdc14ac253f530c71f236
|
@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::Unit::HarnessUnit;
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $r = Test::Unit::HarnessUnit->new();
|
|
||||||
$r->start("ProFTPD::Tests::Config::MaxHostsPerUser");
|
|
@ -1,66 +0,0 @@
|
|||||||
package ProFTPD::TestSuite::ProxiedFTP;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use vars qw(@ISA);
|
|
||||||
|
|
||||||
use Carp;
|
|
||||||
use Net::FTP;
|
|
||||||
|
|
||||||
@ISA = qw(Net::FTP);
|
|
||||||
|
|
||||||
my $proxy_info = undef;
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
my $class = shift;
|
|
||||||
my ($addr, $port, $proxy, $timeout) = @_;
|
|
||||||
$timeout = 5 unless defined($timeout);
|
|
||||||
my $debug = undef;
|
|
||||||
|
|
||||||
$proxy_info = $proxy;
|
|
||||||
|
|
||||||
if ($ENV{TEST_VERBOSE}) {
|
|
||||||
$debug = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $self = $class->SUPER::new($addr,
|
|
||||||
Port => $port,
|
|
||||||
Timeout => $timeout,
|
|
||||||
Debug => $debug,
|
|
||||||
);
|
|
||||||
|
|
||||||
unless ($self) {
|
|
||||||
croak($@);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $self;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Override response() from Net::Cmd to trigger sending the PROXY command
|
|
||||||
sub response {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
if (defined($proxy_info)) {
|
|
||||||
if (ref($proxy_info)) {
|
|
||||||
my ($proto, $src_addr, $dst_addr, $src_port, $dst_port) = @$proxy_info;
|
|
||||||
$self->command("PROXY", $proto, $src_addr, $dst_addr, $src_port, $dst_port);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$self->rawdatasend($proxy_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
$proxy_info = undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->SUPER::response();
|
|
||||||
}
|
|
||||||
|
|
||||||
sub login {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
unless ($self->SUPER::login(@_)) {
|
|
||||||
croak("Failed to login: " . $self->code . " " . $self->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
1;
|
|
@ -1,229 +0,0 @@
|
|||||||
package ProFTPD::Tests::Config::MaxHostsPerUser;
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use base qw(ProFTPD::TestSuite::Child);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use File::Spec;
|
|
||||||
use IO::Handle;
|
|
||||||
|
|
||||||
use ProFTPD::TestSuite::FTP;
|
|
||||||
use ProFTPD::TestSuite::ProxiedFTP;
|
|
||||||
use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $order = 0;
|
|
||||||
|
|
||||||
my $TESTS = {
|
|
||||||
maxhostsperuser_one => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol)],
|
|
||||||
},
|
|
||||||
|
|
||||||
maxhostsperuser_one_multi_conns => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol)],
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
return shift()->SUPER::new(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub list_tests {
|
|
||||||
return testsuite_get_runnable_tests($TESTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub maxhostsperuser_one {
|
|
||||||
my $self = shift;
|
|
||||||
my $tmpdir = $self->{tmpdir};
|
|
||||||
my $setup = test_setup($tmpdir, 'config');
|
|
||||||
|
|
||||||
my $max_hosts = 1;
|
|
||||||
|
|
||||||
my $config = {
|
|
||||||
PidFile => $setup->{pid_file},
|
|
||||||
ScoreboardFile => $setup->{scoreboard_file},
|
|
||||||
SystemLog => $setup->{log_file},
|
|
||||||
|
|
||||||
AuthUserFile => $setup->{auth_user_file},
|
|
||||||
AuthGroupFile => $setup->{auth_group_file},
|
|
||||||
|
|
||||||
MaxHostsPerUser => $max_hosts,
|
|
||||||
|
|
||||||
IfModules => {
|
|
||||||
'mod_delay.c' => {
|
|
||||||
DelayEngine => 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_proxy_protocol.c' => {
|
|
||||||
ProxyProtocolEngine => 'on',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
|
||||||
$config);
|
|
||||||
|
|
||||||
my $proxy_info = ['TCP4', '1.1.1.1', '127.0.0.1', 111, $port];
|
|
||||||
|
|
||||||
# Open pipes, for use between the parent and child processes. Specifically,
|
|
||||||
# the child will indicate when it's done with its test by writing a message
|
|
||||||
# to the parent.
|
|
||||||
my ($rfh, $wfh);
|
|
||||||
unless (pipe($rfh, $wfh)) {
|
|
||||||
die("Can't open pipe: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ex;
|
|
||||||
|
|
||||||
# Fork child
|
|
||||||
$self->handle_sigchld();
|
|
||||||
defined(my $pid = fork()) or die("Can't fork: $!");
|
|
||||||
if ($pid) {
|
|
||||||
eval {
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
# First client should be able to connect and log in...
|
|
||||||
my $client1 = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
['TCP4', '127.0.0.1', '127.0.0.1', 12345, $port]);
|
|
||||||
$client1->login($setup->{user}, $setup->{passwd});
|
|
||||||
|
|
||||||
# ...but the second client should be able to connect, but not login.
|
|
||||||
my $client2 = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
$proxy_info);
|
|
||||||
eval { $client2->login($setup->{user}, $setup->{passwd}) };
|
|
||||||
unless ($@) {
|
|
||||||
die("Login succeeded unexpectedly");
|
|
||||||
}
|
|
||||||
|
|
||||||
$client1->quit();
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$ex = $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wfh->print("done\n");
|
|
||||||
$wfh->flush();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eval { server_wait($setup->{config_file}, $rfh) };
|
|
||||||
if ($@) {
|
|
||||||
warn($@);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stop server
|
|
||||||
server_stop($setup->{pid_file});
|
|
||||||
$self->assert_child_ok($pid);
|
|
||||||
|
|
||||||
test_cleanup($setup->{log_file}, $ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub maxhostsperuser_one_multi_conns {
|
|
||||||
my $self = shift;
|
|
||||||
my $tmpdir = $self->{tmpdir};
|
|
||||||
my $setup = test_setup($tmpdir, 'config');
|
|
||||||
|
|
||||||
my $max_hosts = 1;
|
|
||||||
|
|
||||||
my $config = {
|
|
||||||
PidFile => $setup->{pid_file},
|
|
||||||
ScoreboardFile => $setup->{scoreboard_file},
|
|
||||||
SystemLog => $setup->{log_file},
|
|
||||||
|
|
||||||
AuthUserFile => $setup->{auth_user_file},
|
|
||||||
AuthGroupFile => $setup->{auth_group_file},
|
|
||||||
|
|
||||||
MaxHostsPerUser => $max_hosts,
|
|
||||||
|
|
||||||
IfModules => {
|
|
||||||
'mod_delay.c' => {
|
|
||||||
DelayEngine => 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_proxy_protocol.c' => {
|
|
||||||
ProxyProtocolEngine => 'on',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
|
||||||
$config);
|
|
||||||
|
|
||||||
my $proxy_info = ['TCP4', '1.1.1.1', '127.0.0.1', 111, $port];
|
|
||||||
|
|
||||||
# Open pipes, for use between the parent and child processes. Specifically,
|
|
||||||
# the child will indicate when it's done with its test by writing a message
|
|
||||||
# to the parent.
|
|
||||||
my ($rfh, $wfh);
|
|
||||||
unless (pipe($rfh, $wfh)) {
|
|
||||||
die("Can't open pipe: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ex;
|
|
||||||
|
|
||||||
# Fork child
|
|
||||||
$self->handle_sigchld();
|
|
||||||
defined(my $pid = fork()) or die("Can't fork: $!");
|
|
||||||
if ($pid) {
|
|
||||||
eval {
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
# First client should be able to connect and log in...
|
|
||||||
my $client1 = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
['TCP4', '127.0.0.1', '127.0.0.1', 12345, $port]);
|
|
||||||
$client1->login($setup->{user}, $setup->{passwd});
|
|
||||||
|
|
||||||
# ...but the second client should be able to connect, but not login.
|
|
||||||
my $client2 = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
$proxy_info);
|
|
||||||
eval { $client2->login($setup->{user}, $setup->{passwd}) };
|
|
||||||
unless ($@) {
|
|
||||||
die("Login succeeded unexpectedly");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Even though we can't log in, we should be able to connect quite
|
|
||||||
# a few more times
|
|
||||||
|
|
||||||
my $clients = [];
|
|
||||||
for (my $i = 0; $i < 10; $i++) {
|
|
||||||
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
$proxy_info);
|
|
||||||
push(@$clients, $client);
|
|
||||||
}
|
|
||||||
|
|
||||||
$client1->quit();
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$ex = $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wfh->print("done\n");
|
|
||||||
$wfh->flush();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eval { server_wait($setup->{config_file}, $rfh) };
|
|
||||||
if ($@) {
|
|
||||||
warn($@);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stop server
|
|
||||||
server_stop($setup->{pid_file});
|
|
||||||
$self->assert_child_ok($pid);
|
|
||||||
|
|
||||||
test_cleanup($setup->{log_file}, $ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
File diff suppressed because it is too large
Load Diff
@ -1,150 +0,0 @@
|
|||||||
package ProFTPD::Tests::Modules::mod_proxy_protocol::sftp;
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use base qw(ProFTPD::TestSuite::Child);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use File::Path qw(mkpath);
|
|
||||||
use File::Spec;
|
|
||||||
use IO::Handle;
|
|
||||||
|
|
||||||
use ProFTPD::TestSuite::ProxiedFTP;
|
|
||||||
use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $order = 0;
|
|
||||||
|
|
||||||
my $TESTS = {
|
|
||||||
proxy_protocol_sftp_with_proxy => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol mod_sftp)],
|
|
||||||
},
|
|
||||||
|
|
||||||
proxy_protocol_sftp_without_proxy => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol mod_sftp)],
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
return shift()->SUPER::new(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub list_tests {
|
|
||||||
# return testsuite_get_runnable_tests($TESTS);
|
|
||||||
return qw(
|
|
||||||
proxy_protocol_sftp_with_proxy
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub set_up {
|
|
||||||
my $self = shift;
|
|
||||||
$self->SUPER::set_up(@_);
|
|
||||||
|
|
||||||
# Make sure that mod_sftp does not complain about permissions on the hostkey
|
|
||||||
# files.
|
|
||||||
|
|
||||||
my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
|
|
||||||
my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
|
|
||||||
|
|
||||||
unless (chmod(0400, $rsa_host_key, $dsa_host_key)) {
|
|
||||||
die("Can't set perms on $rsa_host_key, $dsa_host_key: $!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub proxy_protocol_sftp_with_proxy {
|
|
||||||
my $self = shift;
|
|
||||||
my $tmpdir = $self->{tmpdir};
|
|
||||||
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
|
||||||
|
|
||||||
my $rsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_rsa_key");
|
|
||||||
my $dsa_host_key = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_sftp/ssh_host_dsa_key");
|
|
||||||
|
|
||||||
my $config = {
|
|
||||||
PidFile => $setup->{pid_file},
|
|
||||||
ScoreboardFile => $setup->{scoreboard_file},
|
|
||||||
SystemLog => $setup->{log_file},
|
|
||||||
TraceLog => $setup->{log_file},
|
|
||||||
Trace => 'ssh2:20',
|
|
||||||
|
|
||||||
AuthUserFile => $setup->{auth_user_file},
|
|
||||||
AuthGroupFile => $setup->{auth_group_file},
|
|
||||||
|
|
||||||
IfModules => {
|
|
||||||
'mod_delay.c' => {
|
|
||||||
DelayEngine => 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_proxy_protocol.c' => {
|
|
||||||
ProxyProtocolEngine => 'on',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_sftp.c' => [
|
|
||||||
"SFTPEngine on",
|
|
||||||
"SFTPLog $setup->{log_file}",
|
|
||||||
"SFTPHostKey $rsa_host_key",
|
|
||||||
"SFTPHostKey $dsa_host_key",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
|
||||||
$config);
|
|
||||||
|
|
||||||
# Open pipes, for use between the parent and child processes. Specifically,
|
|
||||||
# the child will indicate when it's done with its test by writing a message
|
|
||||||
# to the parent.
|
|
||||||
my ($rfh, $wfh);
|
|
||||||
unless (pipe($rfh, $wfh)) {
|
|
||||||
die("Can't open pipe: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ex;
|
|
||||||
|
|
||||||
# Fork child
|
|
||||||
$self->handle_sigchld();
|
|
||||||
defined(my $pid = fork()) or die("Can't fork: $!");
|
|
||||||
if ($pid) {
|
|
||||||
eval {
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port);
|
|
||||||
$client->send_proxy_raw('1.1.1.1', '2.2.2.2', 111, 222);
|
|
||||||
my $banner = $client->getline();
|
|
||||||
chomp($banner);
|
|
||||||
|
|
||||||
unless ($banner =~ /^SSH\-2\.0\-mod_sftp/) {
|
|
||||||
die("Received unexpected banner from mod_sftp: '$banner'");
|
|
||||||
}
|
|
||||||
|
|
||||||
print $client "SSH-2.0-ProFTPD_mod_proxy_protocol_sftp_Test\r\n";
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$ex = $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wfh->print("done\n");
|
|
||||||
$wfh->flush();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
|
||||||
if ($@) {
|
|
||||||
warn($@);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stop server
|
|
||||||
server_stop($setup->{pid_file});
|
|
||||||
|
|
||||||
$self->assert_child_ok($pid);
|
|
||||||
|
|
||||||
test_cleanup($setup->{log_file}, $ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -1,304 +0,0 @@
|
|||||||
package ProFTPD::Tests::Modules::mod_proxy_protocol::tls;
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use base qw(ProFTPD::TestSuite::Child);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use File::Path qw(mkpath);
|
|
||||||
use File::Spec;
|
|
||||||
use IO::Handle;
|
|
||||||
use Net::Cmd qw(CMD_OK CMD_MORE);
|
|
||||||
|
|
||||||
use ProFTPD::TestSuite::ProxiedFTP;
|
|
||||||
use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $order = 0;
|
|
||||||
|
|
||||||
my $TESTS = {
|
|
||||||
proxy_protocol_tls_login_with_proxy => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol mod_tls)],
|
|
||||||
},
|
|
||||||
|
|
||||||
proxy_protocol_tls_login_with_proxy_useimplicitssl => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol mod_tls)],
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
return shift()->SUPER::new(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub list_tests {
|
|
||||||
# Check for the required Perl modules:
|
|
||||||
#
|
|
||||||
# Net-SSLeay
|
|
||||||
# IO-Socket-SSL
|
|
||||||
|
|
||||||
my $required = [qw(
|
|
||||||
Net::SSLeay
|
|
||||||
IO::Socket::SSL
|
|
||||||
)];
|
|
||||||
|
|
||||||
foreach my $req (@$required) {
|
|
||||||
eval "use $req";
|
|
||||||
if ($@) {
|
|
||||||
print STDERR "\nWARNING:\n + Module '$req' not found, skipping all tests\n";
|
|
||||||
|
|
||||||
if ($ENV{TEST_VERBOSE}) {
|
|
||||||
print STDERR "Unable to load $req: $@\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return qw(testsuite_empty_test);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# return testsuite_get_runnable_tests($TESTS);
|
|
||||||
return qw(
|
|
||||||
proxy_protocol_tls_login_with_proxy_useimplicitssl
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub proxy_protocol_tls_login_with_proxy {
|
|
||||||
my $self = shift;
|
|
||||||
my $tmpdir = $self->{tmpdir};
|
|
||||||
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
|
||||||
|
|
||||||
my $server_cert_file = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_tls/server-cert.pem");
|
|
||||||
my $ca_file = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_tls/ca-cert.pem");
|
|
||||||
|
|
||||||
my $config = {
|
|
||||||
PidFile => $setup->{pid_file},
|
|
||||||
ScoreboardFile => $setup->{scoreboard_file},
|
|
||||||
SystemLog => $setup->{log_file},
|
|
||||||
TraceLog => $setup->{log_file},
|
|
||||||
Trace => 'netio:10 proxy_protocol:20',
|
|
||||||
|
|
||||||
AuthUserFile => $setup->{auth_user_file},
|
|
||||||
AuthGroupFile => $setup->{auth_group_file},
|
|
||||||
|
|
||||||
IfModules => {
|
|
||||||
'mod_delay.c' => {
|
|
||||||
DelayEngine => 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_proxy_protocol.c' => {
|
|
||||||
ProxyProtocolEngine => 'on',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_tls.c' => {
|
|
||||||
TLSEngine => 'on',
|
|
||||||
TLSLog => $setup->{log_file},
|
|
||||||
TLSProtocol => 'SSLv3 TLSv1',
|
|
||||||
TLSRequired => 'on',
|
|
||||||
TLSRSACertificateFile => $server_cert_file,
|
|
||||||
TLSCACertificateFile => $ca_file,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
|
||||||
$config);
|
|
||||||
|
|
||||||
# Open pipes, for use between the parent and child processes. Specifically,
|
|
||||||
# the child will indicate when it's done with its test by writing a message
|
|
||||||
# to the parent.
|
|
||||||
my ($rfh, $wfh);
|
|
||||||
unless (pipe($rfh, $wfh)) {
|
|
||||||
die("Can't open pipe: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ex;
|
|
||||||
|
|
||||||
require IO::Socket::SSL;
|
|
||||||
|
|
||||||
# Fork child
|
|
||||||
$self->handle_sigchld();
|
|
||||||
defined(my $pid = fork()) or die("Can't fork: $!");
|
|
||||||
if ($pid) {
|
|
||||||
eval {
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
|
||||||
my $ok = $client->command("AUTH", "TLS")->response();
|
|
||||||
unless ($ok == CMD_OK || $ok == CMD_MORE) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ssl_opts = {
|
|
||||||
SSL_version => 'SSLv23',
|
|
||||||
};
|
|
||||||
|
|
||||||
my $ssl_client = IO::Socket::SSL->start_SSL($client, %$ssl_opts);
|
|
||||||
unless ($ssl_client) {
|
|
||||||
die("TLS handshake failed: " . IO::Socket::SSL::errstr());
|
|
||||||
}
|
|
||||||
|
|
||||||
push(@IO::Socket::SSL::ISA, 'Net::Cmd');
|
|
||||||
|
|
||||||
$ok = $ssl_client->command("USER", $setup->{user})->response();
|
|
||||||
unless ($ok == CMD_OK || $ok == CMD_MORE) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ok = $ssl_client->command("PASS", $setup->{passwd})->response();
|
|
||||||
unless ($ok == CMD_OK || $ok == CMD_MORE) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ok = $ssl_client->command("QUIT")->response();
|
|
||||||
unless ($ok == CMD_OK) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$ex = $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wfh->print("done\n");
|
|
||||||
$wfh->flush();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
|
||||||
if ($@) {
|
|
||||||
warn($@);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stop server
|
|
||||||
server_stop($setup->{pid_file});
|
|
||||||
|
|
||||||
$self->assert_child_ok($pid);
|
|
||||||
|
|
||||||
test_cleanup($setup->{log_file}, $ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub proxy_protocol_tls_login_with_proxy_useimplicitssl {
|
|
||||||
my $self = shift;
|
|
||||||
my $tmpdir = $self->{tmpdir};
|
|
||||||
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
|
||||||
|
|
||||||
my $server_cert_file = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_tls/server-cert.pem");
|
|
||||||
my $ca_file = File::Spec->rel2abs("$ENV{PROFTPD_TEST_DIR}/t/etc/modules/mod_tls/ca-cert.pem");
|
|
||||||
|
|
||||||
my $config = {
|
|
||||||
PidFile => $setup->{pid_file},
|
|
||||||
ScoreboardFile => $setup->{scoreboard_file},
|
|
||||||
SystemLog => $setup->{log_file},
|
|
||||||
|
|
||||||
AuthUserFile => $setup->{auth_user_file},
|
|
||||||
AuthGroupFile => $setup->{auth_group_file},
|
|
||||||
|
|
||||||
IfModules => {
|
|
||||||
'mod_delay.c' => {
|
|
||||||
DelayEngine => 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_proxy_protocol.c' => {
|
|
||||||
ProxyProtocolEngine => 'on',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_tls.c' => {
|
|
||||||
TLSEngine => 'on',
|
|
||||||
TLSLog => $setup->{log_file},
|
|
||||||
TLSProtocol => 'SSLv3 TLSv1',
|
|
||||||
TLSRequired => 'on',
|
|
||||||
TLSRSACertificateFile => $server_cert_file,
|
|
||||||
TLSCACertificateFile => $ca_file,
|
|
||||||
TLSOptions => 'UseImplicitSSL',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
|
||||||
$config);
|
|
||||||
|
|
||||||
# Open pipes, for use between the parent and child processes. Specifically,
|
|
||||||
# the child will indicate when it's done with its test by writing a message
|
|
||||||
# to the parent.
|
|
||||||
my ($rfh, $wfh);
|
|
||||||
unless (pipe($rfh, $wfh)) {
|
|
||||||
die("Can't open pipe: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ex;
|
|
||||||
|
|
||||||
require IO::Socket::SSL;
|
|
||||||
|
|
||||||
# Fork child
|
|
||||||
$self->handle_sigchld();
|
|
||||||
defined(my $pid = fork()) or die("Can't fork: $!");
|
|
||||||
if ($pid) {
|
|
||||||
eval {
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port,
|
|
||||||
['TCP4', '1.1.1.1', '2.2.2.2', 111, 222]);
|
|
||||||
|
|
||||||
my $ssl_opts = {
|
|
||||||
SSL_version => 'SSLv23',
|
|
||||||
};
|
|
||||||
|
|
||||||
my $ssl_client = IO::Socket::SSL->start_SSL($client, %$ssl_opts);
|
|
||||||
unless ($ssl_client) {
|
|
||||||
die("TLS handshake failed: " . IO::Socket::SSL::errstr());
|
|
||||||
}
|
|
||||||
|
|
||||||
push(@IO::Socket::SSL::ISA, 'Net::Cmd');
|
|
||||||
|
|
||||||
my $ok = $ssl_client->response();
|
|
||||||
unless ($ok == CMD_OK || $ok == CMD_MORE) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ok = $ssl_client->command("USER", $setup->{user})->response();
|
|
||||||
unless ($ok == CMD_OK || $ok == CMD_MORE) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ok = $ssl_client->command("PASS", $setup->{passwd})->response();
|
|
||||||
unless ($ok == CMD_OK || $ok == CMD_MORE) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ok = $ssl_client->command("QUIT")->response();
|
|
||||||
unless ($ok == CMD_OK) {
|
|
||||||
die($client->message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$ex = $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wfh->print("done\n");
|
|
||||||
$wfh->flush();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
|
||||||
if ($@) {
|
|
||||||
warn($@);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stop server
|
|
||||||
server_stop($setup->{pid_file});
|
|
||||||
|
|
||||||
$self->assert_child_ok($pid);
|
|
||||||
|
|
||||||
test_cleanup($setup->{log_file}, $ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -1,139 +0,0 @@
|
|||||||
package ProFTPD::Tests::Modules::mod_proxy_protocol::wrap2;
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use base qw(ProFTPD::TestSuite::Child);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use File::Path qw(mkpath);
|
|
||||||
use File::Spec;
|
|
||||||
use IO::Handle;
|
|
||||||
|
|
||||||
use ProFTPD::TestSuite::ProxiedFTP;
|
|
||||||
use ProFTPD::TestSuite::Utils qw(:auth :config :running :test :testsuite);
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $order = 0;
|
|
||||||
|
|
||||||
my $TESTS = {
|
|
||||||
proxy_protocol_wrap2_config_deny => {
|
|
||||||
order => ++$order,
|
|
||||||
test_class => [qw(forking mod_proxy_protocol mod_wrap2)],
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
sub new {
|
|
||||||
return shift()->SUPER::new(@_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub list_tests {
|
|
||||||
return testsuite_get_runnable_tests($TESTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub proxy_protocol_wrap2_config_deny {
|
|
||||||
my $self = shift;
|
|
||||||
my $tmpdir = $self->{tmpdir};
|
|
||||||
my $setup = test_setup($tmpdir, 'proxy_protocol');
|
|
||||||
|
|
||||||
my $allow_file = File::Spec->rel2abs("$tmpdir/wrap2.allow");
|
|
||||||
if (open(my $fh, "> $allow_file")) {
|
|
||||||
unless (close($fh)) {
|
|
||||||
die("Can't write $allow_file: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
die("Can't open $allow_file: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $deny_file = File::Spec->rel2abs("$tmpdir/wrap2.deny");
|
|
||||||
if (open(my $fh, "> $deny_file")) {
|
|
||||||
print $fh "ALL: 1.1.1.1\n";
|
|
||||||
|
|
||||||
unless (close($fh)) {
|
|
||||||
die("Can't write $deny_file: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
die("Can't open $deny_file: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $config = {
|
|
||||||
PidFile => $setup->{pid_file},
|
|
||||||
ScoreboardFile => $setup->{scoreboard_file},
|
|
||||||
SystemLog => $setup->{log_file},
|
|
||||||
|
|
||||||
AuthUserFile => $setup->{auth_user_file},
|
|
||||||
AuthGroupFile => $setup->{auth_group_file},
|
|
||||||
|
|
||||||
IfModules => {
|
|
||||||
'mod_delay.c' => {
|
|
||||||
DelayEngine => 'off',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_proxy_protocol.c' => {
|
|
||||||
ProxyProtocolEngine => 'on',
|
|
||||||
},
|
|
||||||
|
|
||||||
'mod_wrap2.c' => {
|
|
||||||
WrapEngine => 'on',
|
|
||||||
WrapTables => "file:$allow_file file:$deny_file",
|
|
||||||
WrapLog => $setup->{log_file},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
my ($port, $config_user, $config_group) = config_write($setup->{config_file},
|
|
||||||
$config);
|
|
||||||
|
|
||||||
# Open pipes, for use between the parent and child processes. Specifically,
|
|
||||||
# the child will indicate when it's done with its test by writing a message
|
|
||||||
# to the parent.
|
|
||||||
my ($rfh, $wfh);
|
|
||||||
unless (pipe($rfh, $wfh)) {
|
|
||||||
die("Can't open pipe: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $ex;
|
|
||||||
|
|
||||||
# Fork child
|
|
||||||
$self->handle_sigchld();
|
|
||||||
defined(my $pid = fork()) or die("Can't fork: $!");
|
|
||||||
if ($pid) {
|
|
||||||
eval {
|
|
||||||
sleep(2);
|
|
||||||
|
|
||||||
my $client = ProFTPD::TestSuite::ProxiedFTP->new('127.0.0.1', $port);
|
|
||||||
$client->send_proxy('1.1.1.1', '2.2.2.2', 111, 222);
|
|
||||||
eval { $client->login($setup->{user}, $setup->{passwd}) };
|
|
||||||
unless ($@) {
|
|
||||||
die("Login succeeded unexpectedly");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$ex = $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wfh->print("done\n");
|
|
||||||
$wfh->flush();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
eval { server_wait($setup->{config_file}, $rfh, 10) };
|
|
||||||
if ($@) {
|
|
||||||
warn($@);
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Stop server
|
|
||||||
server_stop($setup->{pid_file});
|
|
||||||
|
|
||||||
$self->assert_child_ok($pid);
|
|
||||||
|
|
||||||
test_cleanup($setup->{log_file}, $ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::Unit::HarnessUnit;
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $r = Test::Unit::HarnessUnit->new();
|
|
||||||
$r->start("ProFTPD::Tests::Modules::mod_proxy_protocol");
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::Unit::HarnessUnit;
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $r = Test::Unit::HarnessUnit->new();
|
|
||||||
$r->start("ProFTPD::Tests::Modules::mod_proxy_protocol::sftp");
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::Unit::HarnessUnit;
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $r = Test::Unit::HarnessUnit->new();
|
|
||||||
$r->start("ProFTPD::Tests::Modules::mod_proxy_protocol::tls");
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
use lib qw(t/lib);
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
use Test::Unit::HarnessUnit;
|
|
||||||
|
|
||||||
$| = 1;
|
|
||||||
|
|
||||||
my $r = Test::Unit::HarnessUnit->new();
|
|
||||||
$r->start("ProFTPD::Tests::Modules::mod_proxy_protocol::wrap2");
|
|
Loading…
Reference in New Issue
Block a user