Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py
+++ django/db/models/fields/related.py
@@ -998,6 +998,9 @@
         if kwargs['rel'].through is not None:
             assert self.db_table is None, "Cannot specify a db_table if an intermediary model is used."
 
+        self.source_fk_name = kwargs.pop('source_fk_name', None)
+        self.target_fk_name = kwargs.pop('target_fk_name', None)
+
         Field.__init__(self, **kwargs)
 
         msg = _('Hold down "Control", or "Command" on a Mac, to select more than one.')
@@ -1023,8 +1026,9 @@
             return getattr(self, cache_attr)
         for f in self.rel.through._meta.fields:
             if hasattr(f,'rel') and f.rel and f.rel.to == related.model:
-                setattr(self, cache_attr, getattr(f, attr))
-                return getattr(self, cache_attr)
+                if not self.source_fk_name or self.source_fk_name == f.name:
+                    setattr(self, cache_attr, getattr(f, attr))
+                    return getattr(self, cache_attr)
 
     def _get_m2m_reverse_attr(self, related, attr):
         "Function that can be curried to provide the related accessor or DB column name for the m2m table"
@@ -1034,7 +1038,7 @@
         found = False
         for f in self.rel.through._meta.fields:
             if hasattr(f,'rel') and f.rel and f.rel.to == related.parent_model:
-                if related.model == related.parent_model:
+                if not self.target_fk_name and related.model == related.parent_model:
                     # If this is an m2m-intermediate to self,
                     # the first foreign key you find will be
                     # the source column. Keep searching for
@@ -1044,7 +1048,7 @@
                         break
                     else:
                         found = True
-                else:
+                elif not self.target_fk_name or self.target_fk_name == f.name:
                     setattr(self, cache_attr, getattr(f, attr))
                     break
         return getattr(self, cache_attr)
Index: django/core/management/validation.py
===================================================================
--- django/core/management/validation.py
+++ django/core/management/validation.py
@@ -173,34 +173,39 @@ def get_validation_errors(outfile, app=None):
                     rel_to = getattr(inter_field.rel, 'to', None)
                     if from_model == to_model: # relation to self
                         if rel_to == from_model:
-                            seen_self += 1
+                            if (not getattr(f, 'source_fk_name', None) or f.source_fk_name == inter_field.name or
+                                not getattr(f, 'target_fk_name', None) or f.target_fk_name == inter_field.name):
+                                seen_self += 1
                         if seen_self > 2:
                             e.add(opts, "Intermediary model %s has more than "
-                                "two foreign keys to %s, which is ambiguous "
-                                "and is not permitted." % (
+                                "two foreign keys to %s. Add a source_fk_name "
+                                "and a target_fk_name arguments to the definition for '%s'." % (
                                     f.rel.through._meta.object_name,
-                                    from_model._meta.object_name
+                                    from_model._meta.object_name,
+                                    f.name
                                 )
                             )
                     else:
-                        if rel_to == from_model:
+                        if rel_to == from_model and (not getattr(f, 'source_fk_name', None) or f.source_fk_name == inter_field.name):
                             if seen_from:
                                 e.add(opts, "Intermediary model %s has more "
-                                    "than one foreign key to %s, which is "
-                                    "ambiguous and is not permitted." % (
+                                    "than one foreign key to %s. Add a source_fk_name "
+                                    "argument to the definition for '%s'." % (
                                         f.rel.through._meta.object_name,
-                                         from_model._meta.object_name
+                                         from_model._meta.object_name,
+                                         f.name
                                      )
                                  )
                             else:
                                 seen_from = True
-                        elif rel_to == to_model:
+                        elif rel_to == to_model and (not getattr(f, 'target_fk_name', None) or f.target_fk_name == inter_field.name):
                             if seen_to:
                                 e.add(opts, "Intermediary model %s has more "
-                                    "than one foreign key to %s, which is "
-                                    "ambiguous and is not permitted." % (
+                                    "than one foreign key to %s. Add a target_fk_name "
+                                    "argument to the definition for '%s'." % (
                                         f.rel.through._meta.object_name,
-                                        rel_to._meta.object_name
+                                        rel_to._meta.object_name,
+                                        f.name
                                     )
                                 )
                             else:
Index: docs/topics/db/models.txt
===================================================================
--- docs/topics/db/models.txt
+++ docs/topics/db/models.txt
@@ -435,19 +435,27 @@
 
 There are a few restrictions on the intermediate model:
 
-    * Your intermediate model must contain one - and *only* one - foreign key
-      to the target model (this would be ``Person`` in our example). If you
-      have more than one foreign key, a validation error will be raised.
-
-    * Your intermediate model must contain one - and *only* one - foreign key
-      to the source model (this would be ``Group`` in our example). If you
-      have more than one foreign key, a validation error will be raised.
+    * To automatically detect the target foreign key, your intermediate model
+      must contain one - and *only* one - foreign key to the target model (this
+      would be ``Person`` in our example). If you have more than one foreign
+      key, you will need to specify the field name by adding a
+      :attr:`~django.db.models.ManyToManyField.target_fk_name`.
+
+    * To automatically detect the source foreign key, your intermediate model
+      must contain one - and *only* one - foreign key to the source model (this
+      would be ``Group`` in our example). If you have more than one foreign key,
+      you will need to specify the field name by adding a
+      :attr:`~django.db.models.ManyToManyField.source_fk_name`.
 
     * The only exception to this is a model which has a many-to-many
       relationship to itself, through an intermediary model. In this
       case, two foreign keys to the same model are permitted, but they
       will be treated as the two (different) sides of the many-to-many
-      relation.
+      relation. If more than two foreign keys exist, or if you want to
+      explicitly specify which field is the target and which is the source,
+      you will need to specify the field names by adding a
+      :attr:`~django.db.models.ManyToManyField.target_fk_name` and a
+      :attr:`~django.db.models.ManyToManyField.source_fk_name`.
 
     * When defining a many-to-many relationship from a model to
       itself, using an intermediary model, you *must* use
Index: tests/modeltests/invalid_models/invalid_models/models.py
===================================================================
--- tests/modeltests/invalid_models/invalid_models/models.py
+++ tests/modeltests/invalid_models/invalid_models/models.py
@@ -326,9 +326,9 @@
 invalid_models.grouptwo: 'secondary' is a manually-defined m2m relation through model MembershipMissingFK, which does not have foreign keys to Group and GroupTwo
 invalid_models.missingmanualm2mmodel: 'missing_m2m' specifies an m2m relation through model MissingM2MModel, which has not been installed
 invalid_models.group: The model Group has two manually-defined m2m relations through the model Membership, which is not permitted. Please consider using an extra field on your intermediary model instead.
-invalid_models.group: Intermediary model RelationshipDoubleFK has more than one foreign key to Person, which is ambiguous and is not permitted.
+invalid_models.group: Intermediary model RelationshipDoubleFK has more than one foreign key to Person. Add a target_fk_name argument to the definition for 'tertiary'.
 invalid_models.personselfrefm2m: Many-to-many fields with intermediate tables cannot be symmetrical.
-invalid_models.personselfrefm2m: Intermediary model RelationshipTripleFK has more than two foreign keys to PersonSelfRefM2M, which is ambiguous and is not permitted.
+invalid_models.personselfrefm2m: Intermediary model RelationshipTripleFK has more than two foreign keys to PersonSelfRefM2M. Add a source_fk_name and a target_fk_name arguments to the definition for 'too_many_friends'.
 invalid_models.personselfrefm2mexplicit: Many-to-many fields with intermediate tables cannot be symmetrical.
 invalid_models.abstractrelationmodel: 'fk1' has a relation with model AbstractModel, which has either not been installed or is abstract.
 invalid_models.abstractrelationmodel: 'fk2' has an m2m relation with model AbstractModel, which has either not been installed or is abstract.
